{
  "cells": [
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "zaLEy7issHF-"
      },
      "source": [
        "# 安装相关程序库"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 4,
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "TbNHzwH3kU4f",
        "outputId": "a57e4e8e-37db-4d30-b0cc-b8c85bdd3584"
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Requirement already satisfied: transformers in /Users/minp/miniconda3/envs/llm_notebooks/lib/python3.12/site-packages (4.36.0)\n",
            "Requirement already satisfied: wikipedia in /Users/minp/miniconda3/envs/llm_notebooks/lib/python3.12/site-packages (1.4.0)\n",
            "Requirement already satisfied: newspaper3k in /Users/minp/miniconda3/envs/llm_notebooks/lib/python3.12/site-packages (0.2.8)\n",
            "Requirement already satisfied: GoogleNews in /Users/minp/miniconda3/envs/llm_notebooks/lib/python3.12/site-packages (1.6.11)\n",
            "Requirement already satisfied: pyvis in /Users/minp/miniconda3/envs/llm_notebooks/lib/python3.12/site-packages (0.3.2)\n",
            "Requirement already satisfied: filelock in /Users/minp/miniconda3/envs/llm_notebooks/lib/python3.12/site-packages (from transformers) (3.13.1)\n",
            "Requirement already satisfied: huggingface-hub<1.0,>=0.19.3 in /Users/minp/miniconda3/envs/llm_notebooks/lib/python3.12/site-packages (from transformers) (0.19.4)\n",
            "Requirement already satisfied: numpy>=1.17 in /Users/minp/miniconda3/envs/llm_notebooks/lib/python3.12/site-packages (from transformers) (1.26.2)\n",
            "Requirement already satisfied: packaging>=20.0 in /Users/minp/miniconda3/envs/llm_notebooks/lib/python3.12/site-packages (from transformers) (23.2)\n",
            "Requirement already satisfied: pyyaml>=5.1 in /Users/minp/miniconda3/envs/llm_notebooks/lib/python3.12/site-packages (from transformers) (6.0.1)\n",
            "Requirement already satisfied: regex!=2019.12.17 in /Users/minp/miniconda3/envs/llm_notebooks/lib/python3.12/site-packages (from transformers) (2023.10.3)\n",
            "Requirement already satisfied: requests in /Users/minp/miniconda3/envs/llm_notebooks/lib/python3.12/site-packages (from transformers) (2.31.0)\n",
            "Requirement already satisfied: tokenizers<0.19,>=0.14 in /Users/minp/miniconda3/envs/llm_notebooks/lib/python3.12/site-packages (from transformers) (0.15.0)\n",
            "Requirement already satisfied: safetensors>=0.3.1 in /Users/minp/miniconda3/envs/llm_notebooks/lib/python3.12/site-packages (from transformers) (0.4.1)\n",
            "Requirement already satisfied: tqdm>=4.27 in /Users/minp/miniconda3/envs/llm_notebooks/lib/python3.12/site-packages (from transformers) (4.66.1)\n",
            "Requirement already satisfied: beautifulsoup4 in /Users/minp/miniconda3/envs/llm_notebooks/lib/python3.12/site-packages (from wikipedia) (4.12.2)\n",
            "Requirement already satisfied: Pillow>=3.3.0 in /Users/minp/miniconda3/envs/llm_notebooks/lib/python3.12/site-packages (from newspaper3k) (10.1.0)\n",
            "Requirement already satisfied: cssselect>=0.9.2 in /Users/minp/miniconda3/envs/llm_notebooks/lib/python3.12/site-packages (from newspaper3k) (1.2.0)\n",
            "Requirement already satisfied: lxml>=3.6.0 in /Users/minp/miniconda3/envs/llm_notebooks/lib/python3.12/site-packages (from newspaper3k) (4.9.3)\n",
            "Requirement already satisfied: nltk>=3.2.1 in /Users/minp/miniconda3/envs/llm_notebooks/lib/python3.12/site-packages (from newspaper3k) (3.8.1)\n",
            "Requirement already satisfied: feedparser>=5.2.1 in /Users/minp/miniconda3/envs/llm_notebooks/lib/python3.12/site-packages (from newspaper3k) (6.0.11)\n",
            "Requirement already satisfied: tldextract>=2.0.1 in /Users/minp/miniconda3/envs/llm_notebooks/lib/python3.12/site-packages (from newspaper3k) (5.1.1)\n",
            "Requirement already satisfied: feedfinder2>=0.0.4 in /Users/minp/miniconda3/envs/llm_notebooks/lib/python3.12/site-packages (from newspaper3k) (0.0.4)\n",
            "Requirement already satisfied: jieba3k>=0.35.1 in /Users/minp/miniconda3/envs/llm_notebooks/lib/python3.12/site-packages (from newspaper3k) (0.35.1)\n",
            "Requirement already satisfied: python-dateutil>=2.5.3 in /Users/minp/miniconda3/envs/llm_notebooks/lib/python3.12/site-packages (from newspaper3k) (2.8.2)\n",
            "Requirement already satisfied: tinysegmenter==0.3 in /Users/minp/miniconda3/envs/llm_notebooks/lib/python3.12/site-packages (from newspaper3k) (0.3)\n",
            "Requirement already satisfied: dateparser in /Users/minp/miniconda3/envs/llm_notebooks/lib/python3.12/site-packages (from GoogleNews) (1.2.0)\n",
            "Requirement already satisfied: ipython>=5.3.0 in /Users/minp/miniconda3/envs/llm_notebooks/lib/python3.12/site-packages (from pyvis) (8.18.1)\n",
            "Requirement already satisfied: jinja2>=2.9.6 in /Users/minp/miniconda3/envs/llm_notebooks/lib/python3.12/site-packages (from pyvis) (3.1.2)\n",
            "Requirement already satisfied: jsonpickle>=1.4.1 in /Users/minp/miniconda3/envs/llm_notebooks/lib/python3.12/site-packages (from pyvis) (3.0.2)\n",
            "Requirement already satisfied: networkx>=1.11 in /Users/minp/miniconda3/envs/llm_notebooks/lib/python3.12/site-packages (from pyvis) (3.2.1)\n",
            "Requirement already satisfied: soupsieve>1.2 in /Users/minp/miniconda3/envs/llm_notebooks/lib/python3.12/site-packages (from beautifulsoup4->wikipedia) (2.5)\n",
            "Requirement already satisfied: six in /Users/minp/miniconda3/envs/llm_notebooks/lib/python3.12/site-packages (from feedfinder2>=0.0.4->newspaper3k) (1.16.0)\n",
            "Requirement already satisfied: sgmllib3k in /Users/minp/miniconda3/envs/llm_notebooks/lib/python3.12/site-packages (from feedparser>=5.2.1->newspaper3k) (1.0.0)\n",
            "Requirement already satisfied: fsspec>=2023.5.0 in /Users/minp/miniconda3/envs/llm_notebooks/lib/python3.12/site-packages (from huggingface-hub<1.0,>=0.19.3->transformers) (2023.12.2)\n",
            "Requirement already satisfied: typing-extensions>=3.7.4.3 in /Users/minp/miniconda3/envs/llm_notebooks/lib/python3.12/site-packages (from huggingface-hub<1.0,>=0.19.3->transformers) (4.9.0)\n",
            "Requirement already satisfied: decorator in /Users/minp/miniconda3/envs/llm_notebooks/lib/python3.12/site-packages (from ipython>=5.3.0->pyvis) (5.1.1)\n",
            "Requirement already satisfied: jedi>=0.16 in /Users/minp/miniconda3/envs/llm_notebooks/lib/python3.12/site-packages (from ipython>=5.3.0->pyvis) (0.19.1)\n",
            "Requirement already satisfied: matplotlib-inline in /Users/minp/miniconda3/envs/llm_notebooks/lib/python3.12/site-packages (from ipython>=5.3.0->pyvis) (0.1.6)\n",
            "Requirement already satisfied: prompt-toolkit<3.1.0,>=3.0.41 in /Users/minp/miniconda3/envs/llm_notebooks/lib/python3.12/site-packages (from ipython>=5.3.0->pyvis) (3.0.41)\n",
            "Requirement already satisfied: pygments>=2.4.0 in /Users/minp/miniconda3/envs/llm_notebooks/lib/python3.12/site-packages (from ipython>=5.3.0->pyvis) (2.17.2)\n",
            "Requirement already satisfied: stack-data in /Users/minp/miniconda3/envs/llm_notebooks/lib/python3.12/site-packages (from ipython>=5.3.0->pyvis) (0.6.2)\n",
            "Requirement already satisfied: traitlets>=5 in /Users/minp/miniconda3/envs/llm_notebooks/lib/python3.12/site-packages (from ipython>=5.3.0->pyvis) (5.14.0)\n",
            "Requirement already satisfied: pexpect>4.3 in /Users/minp/miniconda3/envs/llm_notebooks/lib/python3.12/site-packages (from ipython>=5.3.0->pyvis) (4.8.0)\n",
            "Requirement already satisfied: MarkupSafe>=2.0 in /Users/minp/miniconda3/envs/llm_notebooks/lib/python3.12/site-packages (from jinja2>=2.9.6->pyvis) (2.1.3)\n",
            "Requirement already satisfied: click in /Users/minp/miniconda3/envs/llm_notebooks/lib/python3.12/site-packages (from nltk>=3.2.1->newspaper3k) (8.1.7)\n",
            "Requirement already satisfied: joblib in /Users/minp/miniconda3/envs/llm_notebooks/lib/python3.12/site-packages (from nltk>=3.2.1->newspaper3k) (1.3.2)\n",
            "Requirement already satisfied: charset-normalizer<4,>=2 in /Users/minp/miniconda3/envs/llm_notebooks/lib/python3.12/site-packages (from requests->transformers) (3.3.2)\n",
            "Requirement already satisfied: idna<4,>=2.5 in /Users/minp/miniconda3/envs/llm_notebooks/lib/python3.12/site-packages (from requests->transformers) (3.6)\n",
            "Requirement already satisfied: urllib3<3,>=1.21.1 in /Users/minp/miniconda3/envs/llm_notebooks/lib/python3.12/site-packages (from requests->transformers) (2.1.0)\n",
            "Requirement already satisfied: certifi>=2017.4.17 in /Users/minp/miniconda3/envs/llm_notebooks/lib/python3.12/site-packages (from requests->transformers) (2023.11.17)\n",
            "Requirement already satisfied: requests-file>=1.4 in /Users/minp/miniconda3/envs/llm_notebooks/lib/python3.12/site-packages (from tldextract>=2.0.1->newspaper3k) (1.5.1)\n",
            "Requirement already satisfied: pytz in /Users/minp/miniconda3/envs/llm_notebooks/lib/python3.12/site-packages (from dateparser->GoogleNews) (2023.3.post1)\n",
            "Requirement already satisfied: tzlocal in /Users/minp/miniconda3/envs/llm_notebooks/lib/python3.12/site-packages (from dateparser->GoogleNews) (5.2)\n",
            "Requirement already satisfied: parso<0.9.0,>=0.8.3 in /Users/minp/miniconda3/envs/llm_notebooks/lib/python3.12/site-packages (from jedi>=0.16->ipython>=5.3.0->pyvis) (0.8.3)\n",
            "Requirement already satisfied: ptyprocess>=0.5 in /Users/minp/miniconda3/envs/llm_notebooks/lib/python3.12/site-packages (from pexpect>4.3->ipython>=5.3.0->pyvis) (0.7.0)\n",
            "Requirement already satisfied: wcwidth in /Users/minp/miniconda3/envs/llm_notebooks/lib/python3.12/site-packages (from prompt-toolkit<3.1.0,>=3.0.41->ipython>=5.3.0->pyvis) (0.2.12)\n",
            "Requirement already satisfied: executing>=1.2.0 in /Users/minp/miniconda3/envs/llm_notebooks/lib/python3.12/site-packages (from stack-data->ipython>=5.3.0->pyvis) (2.0.1)\n",
            "Requirement already satisfied: asttokens>=2.1.0 in /Users/minp/miniconda3/envs/llm_notebooks/lib/python3.12/site-packages (from stack-data->ipython>=5.3.0->pyvis) (2.4.1)\n",
            "Requirement already satisfied: pure-eval in /Users/minp/miniconda3/envs/llm_notebooks/lib/python3.12/site-packages (from stack-data->ipython>=5.3.0->pyvis) (0.2.2)\n"
          ]
        }
      ],
      "source": [
        "!pip3 install transformers wikipedia newspaper3k GoogleNews pyvis"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 8,
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "\u001b[31mERROR: Could not find a version that satisfies the requirement torch (from versions: none)\u001b[0m\u001b[31m\n",
            "\u001b[0m\u001b[31mERROR: No matching distribution found for torch\u001b[0m\u001b[31m\n",
            "\u001b[0m"
          ]
        }
      ],
      "source": [
        "!pip3 install torch"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [
        {
          "ename": "ModuleNotFoundError",
          "evalue": "No module named 'torch'",
          "output_type": "error",
          "traceback": [
            "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m\n",
            "\u001b[0;31mModuleNotFoundError\u001b[0m                       Traceback (most recent call last)\n",
            "Cell \u001b[0;32mIn[5], line 3\u001b[0m\n",
            "\u001b[1;32m      1\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mtransformers\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m AutoModelForSeq2SeqLM, AutoTokenizer\n",
            "\u001b[1;32m      2\u001b[0m \u001b[38;5;28;01mimport\u001b[39;00m \u001b[38;5;21;01mmath\u001b[39;00m\n",
            "\u001b[0;32m----> 3\u001b[0m \u001b[38;5;28;01mimport\u001b[39;00m \u001b[38;5;21;01mtorch\u001b[39;00m\n",
            "\u001b[1;32m      4\u001b[0m \u001b[38;5;28;01mimport\u001b[39;00m \u001b[38;5;21;01mwikipedia\u001b[39;00m\n",
            "\u001b[1;32m      5\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mnewspaper\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m Article, ArticleException\n",
            "\n",
            "\u001b[0;31mModuleNotFoundError\u001b[0m: No module named 'torch'"
          ]
        }
      ],
      "source": [
        "from transformers import AutoModelForSeq2SeqLM, AutoTokenizer\n",
        "import math\n",
        "import torch\n",
        "import wikipedia\n",
        "from newspaper import Article, ArticleException\n",
        "from GoogleNews import GoogleNews\n",
        "import IPython\n",
        "from pyvis.network import Network"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [
        {
          "ename": "ModuleNotFoundError",
          "evalue": "No module named 'torch'",
          "output_type": "error",
          "traceback": [
            "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m\n",
            "\u001b[0;31mModuleNotFoundError\u001b[0m                       Traceback (most recent call last)\n",
            "Cell \u001b[0;32mIn[5], line 3\u001b[0m\n",
            "\u001b[1;32m      1\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mtransformers\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m AutoModelForSeq2SeqLM, AutoTokenizer\n",
            "\u001b[1;32m      2\u001b[0m \u001b[38;5;28;01mimport\u001b[39;00m \u001b[38;5;21;01mmath\u001b[39;00m\n",
            "\u001b[0;32m----> 3\u001b[0m \u001b[38;5;28;01mimport\u001b[39;00m \u001b[38;5;21;01mtorch\u001b[39;00m\n",
            "\u001b[1;32m      4\u001b[0m \u001b[38;5;28;01mimport\u001b[39;00m \u001b[38;5;21;01mwikipedia\u001b[39;00m\n",
            "\u001b[1;32m      5\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mnewspaper\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m Article, ArticleException\n",
            "\n",
            "\u001b[0;31mModuleNotFoundError\u001b[0m: No module named 'torch'"
          ]
        }
      ],
      "source": [
        "from transformers import AutoModelForSeq2SeqLM, AutoTokenizer\n",
        "import math\n",
        "import torch\n",
        "import wikipedia\n",
        "from newspaper import Article, ArticleException\n",
        "from GoogleNews import GoogleNews\n",
        "import IPython\n",
        "from pyvis.network import Network"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [
        {
          "ename": "ModuleNotFoundError",
          "evalue": "No module named 'torch'",
          "output_type": "error",
          "traceback": [
            "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m\n",
            "\u001b[0;31mModuleNotFoundError\u001b[0m                       Traceback (most recent call last)\n",
            "Cell \u001b[0;32mIn[5], line 3\u001b[0m\n",
            "\u001b[1;32m      1\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mtransformers\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m AutoModelForSeq2SeqLM, AutoTokenizer\n",
            "\u001b[1;32m      2\u001b[0m \u001b[38;5;28;01mimport\u001b[39;00m \u001b[38;5;21;01mmath\u001b[39;00m\n",
            "\u001b[0;32m----> 3\u001b[0m \u001b[38;5;28;01mimport\u001b[39;00m \u001b[38;5;21;01mtorch\u001b[39;00m\n",
            "\u001b[1;32m      4\u001b[0m \u001b[38;5;28;01mimport\u001b[39;00m \u001b[38;5;21;01mwikipedia\u001b[39;00m\n",
            "\u001b[1;32m      5\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mnewspaper\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m Article, ArticleException\n",
            "\n",
            "\u001b[0;31mModuleNotFoundError\u001b[0m: No module named 'torch'"
          ]
        }
      ],
      "source": [
        "from transformers import AutoModelForSeq2SeqLM, AutoTokenizer\n",
        "import math\n",
        "import torch\n",
        "import wikipedia\n",
        "from newspaper import Article, ArticleException\n",
        "from GoogleNews import GoogleNews\n",
        "import IPython\n",
        "from pyvis.network import Network"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 5,
      "metadata": {
        "id": "oMVVc3epkQbC"
      },
      "outputs": [
        {
          "ename": "ModuleNotFoundError",
          "evalue": "No module named 'torch'",
          "output_type": "error",
          "traceback": [
            "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
            "\u001b[0;31mModuleNotFoundError\u001b[0m                       Traceback (most recent call last)",
            "Cell \u001b[0;32mIn[5], line 3\u001b[0m\n\u001b[1;32m      1\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mtransformers\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m AutoModelForSeq2SeqLM, AutoTokenizer\n\u001b[1;32m      2\u001b[0m \u001b[38;5;28;01mimport\u001b[39;00m \u001b[38;5;21;01mmath\u001b[39;00m\n\u001b[0;32m----> 3\u001b[0m \u001b[38;5;28;01mimport\u001b[39;00m \u001b[38;5;21;01mtorch\u001b[39;00m\n\u001b[1;32m      4\u001b[0m \u001b[38;5;28;01mimport\u001b[39;00m \u001b[38;5;21;01mwikipedia\u001b[39;00m\n\u001b[1;32m      5\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mnewspaper\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m Article, ArticleException\n",
            "\u001b[0;31mModuleNotFoundError\u001b[0m: No module named 'torch'"
          ]
        }
      ],
      "source": [
        "from transformers import AutoModelForSeq2SeqLM, AutoTokenizer\n",
        "import math\n",
        "import torch\n",
        "import wikipedia\n",
        "from newspaper import Article, ArticleException\n",
        "from GoogleNews import GoogleNews\n",
        "import IPython\n",
        "from pyvis.network import Network"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "jkU8C2qVsLBh"
      },
      "source": [
        "# 加载 REBEL 模型"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 35,
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "3DUOJhoVltPg",
        "outputId": "b54c7589-96dc-4b1c-8f19-60a7d6911f03"
      },
      "outputs": [
        {
          "name": "stderr",
          "output_type": "stream",
          "text": [
            "Special tokens have been added in the vocabulary, make sure the associated word embeddings are fine-tuned or trained.\n"
          ]
        }
      ],
      "source": [
        "# Load model and tokenizer\n",
        "tokenizer = AutoTokenizer.from_pretrained(\"Babelscape/rebel-large\")\n",
        "model = AutoModelForSeq2SeqLM.from_pretrained(\"Babelscape/rebel-large\")"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "_9T3Sx3RsP8O"
      },
      "source": [
        "# 从短文到 KB"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 36,
      "metadata": {
        "id": "h-DboLAHkj_G"
      },
      "outputs": [],
      "source": [
        "def extract_relations_from_model_output(text):\n",
        "    relations = []\n",
        "    relation, subject, relation, object_ = '', '', '', ''\n",
        "    text = text.strip()\n",
        "    current = 'x'\n",
        "    text_replaced = text.replace(\"<s>\", \"\").replace(\"<pad>\", \"\").replace(\"</s>\", \"\")\n",
        "    for token in text_replaced.split():\n",
        "        if token == \"<triplet>\":\n",
        "            current = 't'\n",
        "            if relation != '':\n",
        "                relations.append({\n",
        "                    'head': subject.strip(),\n",
        "                    'type': relation.strip(),\n",
        "                    'tail': object_.strip()\n",
        "                })\n",
        "                relation = ''\n",
        "            subject = ''\n",
        "        elif token == \"<subj>\":\n",
        "            current = 's'\n",
        "            if relation != '':\n",
        "                relations.append({\n",
        "                    'head': subject.strip(),\n",
        "                    'type': relation.strip(),\n",
        "                    'tail': object_.strip()\n",
        "                })\n",
        "            object_ = ''\n",
        "        elif token == \"<obj>\":\n",
        "            current = 'o'\n",
        "            relation = ''\n",
        "        else:\n",
        "            if current == 't':\n",
        "                subject += ' ' + token\n",
        "            elif current == 's':\n",
        "                object_ += ' ' + token\n",
        "            elif current == 'o':\n",
        "                relation += ' ' + token\n",
        "    if subject != '' and relation != '' and object_ != '':\n",
        "        relations.append({\n",
        "            'head': subject.strip(),\n",
        "            'type': relation.strip(),\n",
        "            'tail': object_.strip()\n",
        "        })\n",
        "    return relations"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 37,
      "metadata": {
        "id": "8WxoMskYHgsm"
      },
      "outputs": [],
      "source": [
        "class KB():\n",
        "    def __init__(self):\n",
        "        self.relations = []\n",
        "\n",
        "    def are_relations_equal(self, r1, r2):\n",
        "        return all(r1[attr] == r2[attr] for attr in [\"head\", \"type\", \"tail\"])\n",
        "\n",
        "    def exists_relation(self, r1):\n",
        "        return any(self.are_relations_equal(r1, r2) for r2 in self.relations)\n",
        "\n",
        "    def add_relation(self, r):\n",
        "        if not self.exists_relation(r):\n",
        "            self.relations.append(r)\n",
        "\n",
        "    def print(self):\n",
        "        print(\"Relations:\")\n",
        "        for r in self.relations:\n",
        "            print(f\"  {r}\")"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 38,
      "metadata": {
        "id": "ijyjp6r1kg2V"
      },
      "outputs": [],
      "source": [
        "def from_small_text_to_kb(text, verbose=False):\n",
        "    kb = KB()\n",
        "\n",
        "    # Tokenizer text\n",
        "    model_inputs = tokenizer(text, max_length=512, padding=True, truncation=True,\n",
        "                            return_tensors='pt')\n",
        "    if verbose:\n",
        "        print(f\"Num tokens: {len(model_inputs['input_ids'][0])}\")\n",
        "\n",
        "    # Generate\n",
        "    gen_kwargs = {\n",
        "        \"max_length\": 216,\n",
        "        \"length_penalty\": 0,\n",
        "        \"num_beams\": 3,\n",
        "        \"num_return_sequences\": 3\n",
        "    }\n",
        "    generated_tokens = model.generate(\n",
        "        **model_inputs,\n",
        "        **gen_kwargs,\n",
        "    )\n",
        "    decoded_preds = tokenizer.batch_decode(generated_tokens, skip_special_tokens=False)\n",
        "\n",
        "    # create kb\n",
        "    for sentence_pred in decoded_preds:\n",
        "        relations = extract_relations_from_model_output(sentence_pred)\n",
        "        for r in relations:\n",
        "            kb.add_relation(r)\n",
        "\n",
        "    return kb"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 39,
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "kPWvl_78kUBX",
        "outputId": "c7f6788d-1dc4-4fad-f2db-f687073f7a67"
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Num tokens: 133\n",
            "Relations:\n",
            "  {'head': 'Napoleon Bonaparte', 'type': 'date of birth', 'tail': '15 August 1769'}\n",
            "  {'head': 'Napoleon Bonaparte', 'type': 'date of death', 'tail': '5 May 1821'}\n",
            "  {'head': 'Napoleon Bonaparte', 'type': 'participant in', 'tail': 'French Revolution'}\n",
            "  {'head': 'Napoleon Bonaparte', 'type': 'conflict', 'tail': 'Revolutionary Wars'}\n",
            "  {'head': 'Revolutionary Wars', 'type': 'part of', 'tail': 'French Revolution'}\n",
            "  {'head': 'French Revolution', 'type': 'participant', 'tail': 'Napoleon Bonaparte'}\n",
            "  {'head': 'Revolutionary Wars', 'type': 'participant', 'tail': 'Napoleon Bonaparte'}\n"
          ]
        }
      ],
      "source": [
        "text = \"Napoleon Bonaparte (born Napoleone di Buonaparte; 15 August 1769 – 5 \" \\\n",
        "\"May 1821), and later known by his regnal name Napoleon I, was a French military \" \\\n",
        "\"and political leader who rose to prominence during the French Revolution and led \" \\\n",
        "\"several successful campaigns during the Revolutionary Wars. He was the de facto \" \\\n",
        "\"leader of the French Republic as First Consul from 1799 to 1804. As Napoleon I, \" \\\n",
        "\"he was Emperor of the French from 1804 until 1814 and again in 1815. Napoleon's \" \\\n",
        "\"political and cultural legacy has endured, and he has been one of the most \" \\\n",
        "\"celebrated and controversial leaders in world history.\"\n",
        "\n",
        "kb = from_small_text_to_kb(text, verbose=True)\n",
        "kb.print()\n",
        "# Num tokens: 133\n",
        "# Relations:\n",
        "#   {'head': 'Napoleon Bonaparte', 'type': 'date of birth', 'tail': '15 August 1769'}\n",
        "#   {'head': 'Napoleon Bonaparte', 'type': 'date of death', 'tail': '5 May 1821'}\n",
        "#   {'head': 'Napoleon Bonaparte', 'type': 'participant in', 'tail': 'French Revolution'}\n",
        "#   {'head': 'Napoleon Bonaparte', 'type': 'conflict', 'tail': 'Revolutionary Wars'}\n",
        "#   {'head': 'Revolutionary Wars', 'type': 'part of', 'tail': 'French Revolution'}\n",
        "#   {'head': 'French Revolution', 'type': 'participant', 'tail': 'Napoleon Bonaparte'}\n",
        "#   {'head': 'Revolutionary Wars', 'type': 'participant', 'tail': 'Napoleon Bonaparte'}"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "MqhLveaeuJNk"
      },
      "source": [
        "# 分割数据：从长文本到 KB"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "i0L2Lw9vJ6-I"
      },
      "outputs": [],
      "source": [
        "class KB():\n",
        "    def __init__(self):\n",
        "        self.relations = []\n",
        "\n",
        "    def are_relations_equal(self, r1, r2):\n",
        "        return all(r1[attr] == r2[attr] for attr in [\"head\", \"type\", \"tail\"])\n",
        "\n",
        "    def exists_relation(self, r1):\n",
        "        return any(self.are_relations_equal(r1, r2) for r2 in self.relations)\n",
        "\n",
        "    def merge_relations(self, r1):\n",
        "        r2 = [r for r in self.relations\n",
        "              if self.are_relations_equal(r1, r)][0]\n",
        "        spans_to_add = [span for span in r1[\"meta\"][\"spans\"]\n",
        "                        if span not in r2[\"meta\"][\"spans\"]]\n",
        "        r2[\"meta\"][\"spans\"] += spans_to_add\n",
        "\n",
        "    def add_relation(self, r):\n",
        "        if not self.exists_relation(r):\n",
        "            self.relations.append(r)\n",
        "        else:\n",
        "            self.merge_relations(r)\n",
        "\n",
        "    def print(self):\n",
        "        print(\"Relations:\")\n",
        "        for r in self.relations:\n",
        "            print(f\"  {r}\")"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "HlnLhlSmuUCs"
      },
      "outputs": [],
      "source": [
        "def from_text_to_kb(text, span_length=128, verbose=False):\n",
        "    # tokenize whole text\n",
        "    inputs = tokenizer([text], return_tensors=\"pt\")\n",
        "\n",
        "    # compute span boundaries\n",
        "    num_tokens = len(inputs[\"input_ids\"][0])\n",
        "    if verbose:\n",
        "        print(f\"Input has {num_tokens} tokens\")\n",
        "    num_spans = math.ceil(num_tokens / span_length)\n",
        "    if verbose:\n",
        "        print(f\"Input has {num_spans} spans\")\n",
        "    overlap = math.ceil((num_spans * span_length - num_tokens) /\n",
        "                        max(num_spans - 1, 1))\n",
        "    spans_boundaries = []\n",
        "    start = 0\n",
        "    for i in range(num_spans):\n",
        "        spans_boundaries.append([start + span_length * i,\n",
        "                                 start + span_length * (i + 1)])\n",
        "        start -= overlap\n",
        "    if verbose:\n",
        "        print(f\"Span boundaries are {spans_boundaries}\")\n",
        "\n",
        "    # transform input with spans\n",
        "    tensor_ids = [inputs[\"input_ids\"][0][boundary[0]:boundary[1]]\n",
        "                  for boundary in spans_boundaries]\n",
        "    tensor_masks = [inputs[\"attention_mask\"][0][boundary[0]:boundary[1]]\n",
        "                    for boundary in spans_boundaries]\n",
        "    inputs = {\n",
        "        \"input_ids\": torch.stack(tensor_ids),\n",
        "        \"attention_mask\": torch.stack(tensor_masks)\n",
        "    }\n",
        "\n",
        "    # generate relations\n",
        "    num_return_sequences = 3\n",
        "    gen_kwargs = {\n",
        "        \"max_length\": 256,\n",
        "        \"length_penalty\": 0,\n",
        "        \"num_beams\": 3,\n",
        "        \"num_return_sequences\": num_return_sequences\n",
        "    }\n",
        "    generated_tokens = model.generate(\n",
        "        **inputs,\n",
        "        **gen_kwargs,\n",
        "    )\n",
        "\n",
        "    # decode relations\n",
        "    decoded_preds = tokenizer.batch_decode(generated_tokens,\n",
        "                                           skip_special_tokens=False)\n",
        "\n",
        "    # create kb\n",
        "    kb = KB()\n",
        "    i = 0\n",
        "    for sentence_pred in decoded_preds:\n",
        "        current_span_index = i // num_return_sequences\n",
        "        relations = extract_relations_from_model_output(sentence_pred)\n",
        "        for relation in relations:\n",
        "            relation[\"meta\"] = {\n",
        "                \"spans\": [spans_boundaries[current_span_index]]\n",
        "            }\n",
        "            kb.add_relation(relation)\n",
        "        i += 1\n",
        "\n",
        "    return kb"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "sXz06j_dne1c",
        "outputId": "783dad43-6e1e-419e-869e-208e4b3b7961"
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Input has 726 tokens\n",
            "Input has 6 spans\n",
            "Span boundaries are [[0, 128], [119, 247], [238, 366], [357, 485], [476, 604], [595, 723]]\n",
            "Relations:\n",
            "  {'head': 'Napoleon Bonaparte', 'type': 'date of birth', 'tail': '15 August 1769', 'meta': {'spans': [[0, 128]]}}\n",
            "  {'head': 'Napoleon Bonaparte', 'type': 'date of death', 'tail': '5 May 1821', 'meta': {'spans': [[0, 128]]}}\n",
            "  {'head': 'Napoleon Bonaparte', 'type': 'participant in', 'tail': 'French Revolution', 'meta': {'spans': [[0, 128]]}}\n",
            "  {'head': 'Napoleon Bonaparte', 'type': 'conflict', 'tail': 'Revolutionary Wars', 'meta': {'spans': [[0, 128]]}}\n",
            "  {'head': 'Revolutionary Wars', 'type': 'part of', 'tail': 'French Revolution', 'meta': {'spans': [[0, 128]]}}\n",
            "  {'head': 'French Revolution', 'type': 'participant', 'tail': 'Napoleon Bonaparte', 'meta': {'spans': [[0, 128]]}}\n",
            "  {'head': 'Revolutionary Wars', 'type': 'participant', 'tail': 'Napoleon Bonaparte', 'meta': {'spans': [[0, 128]]}}\n",
            "  {'head': 'French Revolution', 'type': 'country', 'tail': 'French Republic', 'meta': {'spans': [[0, 128]]}}\n",
            "  {'head': 'Napoleon', 'type': 'place of birth', 'tail': 'Corsica', 'meta': {'spans': [[119, 247]]}}\n",
            "  {'head': 'French Directory', 'type': 'facet of', 'tail': 'French Revolution', 'meta': {'spans': [[119, 247]]}}\n",
            "  {'head': 'Napoleon', 'type': 'participant in', 'tail': 'French Revolution', 'meta': {'spans': [[119, 247]]}}\n",
            "  {'head': 'Fourth Coalition', 'type': 'start time', 'tail': '1806', 'meta': {'spans': [[238, 366]]}}\n",
            "  {'head': 'Ulm Campaign', 'type': 'part of', 'tail': 'War of the Third Coalition', 'meta': {'spans': [[238, 366]]}}\n",
            "  {'head': 'Battle of Austerlitz', 'type': 'part of', 'tail': 'War of the Third Coalition', 'meta': {'spans': [[238, 366]]}}\n",
            "  {'head': 'War of the Third Coalition', 'type': 'start time', 'tail': '1805', 'meta': {'spans': [[238, 366]]}}\n",
            "  {'head': 'Battle of Wagram', 'type': 'part of', 'tail': 'War of the Fifth Coalition', 'meta': {'spans': [[357, 485]]}}\n",
            "  {'head': 'Fourth Coalition', 'type': 'followed by', 'tail': 'War of the Fifth Coalition', 'meta': {'spans': [[357, 485]]}}\n",
            "  {'head': 'Battle of Leipzig', 'type': 'part of', 'tail': 'Sixth Coalition against France', 'meta': {'spans': [[476, 604]]}}\n",
            "  {'head': 'Sixth Coalition against France', 'type': 'start time', 'tail': '1813', 'meta': {'spans': [[476, 604]]}}\n",
            "  {'head': 'Sixth Coalition', 'type': 'start time', 'tail': '1813', 'meta': {'spans': [[476, 604]]}}\n",
            "  {'head': 'Seventh Coalition', 'type': 'has part', 'tail': 'Battle of Waterloo', 'meta': {'spans': [[595, 723]]}}\n",
            "  {'head': 'Battle of Waterloo', 'type': 'part of', 'tail': 'Seventh Coalition', 'meta': {'spans': [[595, 723]]}}\n",
            "  {'head': 'Seventh Coalition', 'type': 'start time', 'tail': 'June 1815', 'meta': {'spans': [[595, 723]]}}\n"
          ]
        }
      ],
      "source": [
        "text = \"\"\"\n",
        "Napoleon Bonaparte (born Napoleone di Buonaparte; 15 August 1769 – 5 May 1821), and later known by his regnal name Napoleon I, was a French military and political leader who rose to prominence during the French Revolution and led several successful campaigns during the Revolutionary Wars. He was the de facto leader of the French Republic as First Consul from 1799 to 1804. As Napoleon I, he was Emperor of the French from 1804 until 1814 and again in 1815. Napoleon's political and cultural legacy has endured, and he has been one of the most celebrated and controversial leaders in world history. Napoleon was born on the island of Corsica not long after its annexation by the Kingdom of France.[5] He supported the French Revolution in 1789 while serving in the French army, and tried to spread its ideals to his native Corsica. He rose rapidly in the Army after he saved the governing French Directory by firing on royalist insurgents. In 1796, he began a military campaign against the Austrians and their Italian allies, scoring decisive victories and becoming a national hero. Two years later, he led a military expedition to Egypt that served as a springboard to political power. He engineered a coup in November 1799 and became First Consul of the Republic. Differences with the British meant that the French faced the War of the Third Coalition by 1805. Napoleon shattered this coalition with victories in the Ulm Campaign, and at the Battle of Austerlitz, which led to the dissolving of the Holy Roman Empire. In 1806, the Fourth Coalition took up arms against him because Prussia became worried about growing French influence on the continent. Napoleon knocked out Prussia at the battles of Jena and Auerstedt, marched the Grande Armée into Eastern Europe, annihilating the Russians in June 1807 at Friedland, and forcing the defeated nations of the Fourth Coalition to accept the Treaties of Tilsit. Two years later, the Austrians challenged the French again during the War of the Fifth Coalition, but Napoleon solidified his grip over Europe after triumphing at the Battle of Wagram. Hoping to extend the Continental System, his embargo against Britain, Napoleon invaded the Iberian Peninsula and declared his brother Joseph King of Spain in 1808. The Spanish and the Portuguese revolted in the Peninsular War, culminating in defeat for Napoleon's marshals. Napoleon launched an invasion of Russia in the summer of 1812. The resulting campaign witnessed the catastrophic retreat of Napoleon's Grande Armée. In 1813, Prussia and Austria joined Russian forces in a Sixth Coalition against France. A chaotic military campaign resulted in a large coalition army defeating Napoleon at the Battle of Leipzig in October 1813. The coalition invaded France and captured Paris, forcing Napoleon to abdicate in April 1814. He was exiled to the island of Elba, between Corsica and Italy. In France, the Bourbons were restored to power. However, Napoleon escaped Elba in February 1815 and took control of France.[6][7] The Allies responded by forming a Seventh Coalition, which defeated Napoleon at the Battle of Waterloo in June 1815. The British exiled him to the remote island of Saint Helena in the Atlantic, where he died in 1821 at the age of 51. Napoleon had an extensive impact on the modern world, bringing liberal reforms to the many countries he conquered, especially the Low Countries, Switzerland, and parts of modern Italy and Germany. He implemented liberal policies in France and Western Europe.\n",
        "\"\"\"\n",
        "\n",
        "kb = from_text_to_kb(text, verbose=True)\n",
        "kb.print()\n",
        "# Input has 726 tokens\n",
        "# Input has 6 spans\n",
        "# Span boundaries are [[0, 128], [119, 247], [238, 366], [357, 485], [476, 604], [595, 723]]\n",
        "# Relations:\n",
        "#   {'head': 'Napoleon Bonaparte', 'type': 'date of birth',\n",
        "#    'tail': '15 August 1769', 'meta': {'spans': [[0, 128]]}}\n",
        "#   ...\n",
        "#   {'head': 'Napoleon', 'type': 'place of birth',\n",
        "#    'tail': 'Corsica', 'meta': {'spans': [[119, 247]]}}\n",
        "#   ...\n",
        "#   {'head': 'Fourth Coalition', 'type': 'start time',\n",
        "#    'tail': '1806', 'meta': {'spans': [[238, 366]]}}\n",
        "#   ..."
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "c13w1wTF61AB"
      },
      "source": [
        "# 利用维基百科对实体进行过滤和规范化处理\n",
        "\n",
        "- 删除所有在维基百科上没有页面的实体\n",
        "- 合并拥有相同维基百科页面的实体"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "JqXxSWICJXBq"
      },
      "outputs": [],
      "source": [
        "class KB():\n",
        "    def __init__(self):\n",
        "        self.entities = {}\n",
        "        self.relations = []\n",
        "\n",
        "    def are_relations_equal(self, r1, r2):\n",
        "        return all(r1[attr] == r2[attr] for attr in [\"head\", \"type\", \"tail\"])\n",
        "\n",
        "    def exists_relation(self, r1):\n",
        "        return any(self.are_relations_equal(r1, r2) for r2 in self.relations)\n",
        "\n",
        "    def merge_relations(self, r1):\n",
        "        r2 = [r for r in self.relations\n",
        "              if self.are_relations_equal(r1, r)][0]\n",
        "        spans_to_add = [span for span in r1[\"meta\"][\"spans\"]\n",
        "                        if span not in r2[\"meta\"][\"spans\"]]\n",
        "        r2[\"meta\"][\"spans\"] += spans_to_add\n",
        "\n",
        "    def get_wikipedia_data(self, candidate_entity):\n",
        "        try:\n",
        "            page = wikipedia.page(candidate_entity, auto_suggest=False)\n",
        "            entity_data = {\n",
        "                \"title\": page.title,\n",
        "                \"url\": page.url,\n",
        "                \"summary\": page.summary\n",
        "            }\n",
        "            return entity_data\n",
        "        except:\n",
        "            return None\n",
        "\n",
        "    def add_entity(self, e):\n",
        "        self.entities[e[\"title\"]] = {k:v for k,v in e.items() if k != \"title\"}\n",
        "\n",
        "    def add_relation(self, r):\n",
        "        # check on wikipedia\n",
        "        candidate_entities = [r[\"head\"], r[\"tail\"]]\n",
        "        entities = [self.get_wikipedia_data(ent) for ent in candidate_entities]\n",
        "\n",
        "        # if one entity does not exist, stop\n",
        "        if any(ent is None for ent in entities):\n",
        "            return\n",
        "\n",
        "        # manage new entities\n",
        "        for e in entities:\n",
        "            self.add_entity(e)\n",
        "\n",
        "        # rename relation entities with their wikipedia titles\n",
        "        r[\"head\"] = entities[0][\"title\"]\n",
        "        r[\"tail\"] = entities[1][\"title\"]\n",
        "\n",
        "        # manage new relation\n",
        "        if not self.exists_relation(r):\n",
        "            self.relations.append(r)\n",
        "        else:\n",
        "            self.merge_relations(r)\n",
        "\n",
        "    def print(self):\n",
        "        print(\"Entities:\")\n",
        "        for e in self.entities.items():\n",
        "            print(f\"  {e}\")\n",
        "        print(\"Relations:\")\n",
        "        for r in self.relations:\n",
        "            print(f\"  {r}\")"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "qEAiQNBhPU4U",
        "outputId": "25cbe34f-1a30-4443-d1d2-acb186266404"
      },
      "outputs": [
        {
          "name": "stderr",
          "output_type": "stream",
          "text": [
            "/usr/local/lib/python3.10/dist-packages/wikipedia/wikipedia.py:389: GuessedAtParserWarning: No parser was explicitly specified, so I'm using the best available HTML parser for this system (\"lxml\"). This usually isn't a problem, but if you run this code on another system, or in a different virtual environment, it may use a different parser and behave differently.\n",
            "\n",
            "The code that caused this warning is on line 389 of the file /usr/local/lib/python3.10/dist-packages/wikipedia/wikipedia.py. To get rid of this warning, pass the additional argument 'features=\"lxml\"' to the BeautifulSoup constructor.\n",
            "\n",
            "  lis = BeautifulSoup(html).find_all('li')\n"
          ]
        },
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Entities:\n",
            "  ('Napoleon', {'url': 'https://en.wikipedia.org/wiki/Napoleon', 'summary': \"Napoleon Bonaparte (born Napoleone di Buonaparte; 15 August 1769 – 5 May 1821), later known by his regnal name Napoleon I, was a French emperor and military commander who rose to prominence during the French Revolution and led successful campaigns during the Revolutionary Wars. He was the leader of the French Republic as First Consul from 1799 to 1804, then of the French Empire as Emperor of the French from 1804 until 1814, and briefly again in 1815. His political and cultural legacy endures as a celebrated and controversial leader. He initiated many enduring reforms, but has been criticized for his authoritarian rule. He is considered one of the greatest military commanders in history and his wars and campaigns are still studied at military schools worldwide. However, historians still debate whether he was responsible for the Napoleonic Wars in which between three and six million people died.Napoleon was born on the island of Corsica into a family descended from Italian nobility. He was resentful of the French monarchy, and supported the French Revolution in 1789 while serving in the French army, trying to spread its ideals to his native Corsica. He rose rapidly in the ranks after saving the governing French Directory by firing on royalist insurgents. In 1796, he began a military campaign against the Austrians and their Italian allies, scoring decisive victories, and became a national hero. Two years later he led a military expedition to Egypt that served as a springboard to political power. He engineered a coup in November 1799 and became First Consul of the Republic. In 1804, to consolidate and expand his power, he crowned himself Emperor of the French.\\nDifferences with the United Kingdom meant France faced the War of the Third Coalition by 1805. Napoleon shattered this coalition with victories in the Ulm campaign and at the Battle of Austerlitz, which led to the dissolution of the Holy Roman Empire. In 1806, the Fourth Coalition took up arms against him. Napoleon defeated Prussia at the battles of Jena and Auerstedt, marched the Grande Armée into Eastern Europe, and defeated the Russians in June 1807 at Friedland, forcing the defeated nations of the Fourth Coalition to accept the Treaties of Tilsit. Two years later, the Austrians challenged the French again during the War of the Fifth Coalition, but Napoleon solidified his grip over Europe after triumphing at the Battle of Wagram.\\nHoping to extend the Continental System, his embargo against Britain, Napoleon invaded the Iberian Peninsula and declared his brother Joseph the King of Spain in 1808. The Spanish and the Portuguese revolted in the Peninsular War aided by a British army, culminating in defeat for Napoleon's marshals. Napoleon launched an invasion of Russia in the summer of 1812. The resulting campaign witnessed the catastrophic retreat of Napoleon's Grande Armée. In 1813, Prussia and Austria joined Russian forces in a Sixth Coalition against France, resulting in a large coalition army defeating Napoleon at the Battle of Leipzig. The coalition invaded France and captured Paris, forcing Napoleon to abdicate in April 1814. He was exiled to the island of Elba, between Corsica and Italy. In France, the Bourbons were restored to power.\\nNapoleon escaped in February 1815 and took control of France. The Allies responded by forming a Seventh Coalition, which defeated Napoleon at the Battle of Waterloo in June 1815. The British exiled him to the remote island of Saint Helena in the Atlantic, where he died in 1821 at the age of 51.\\nNapoleon had a lasting impact on the world, bringing modernizing reforms to France and Western Europe and stimulating the development of nation states. He also sold the Louisiana Territory to the United States in 1803, doubling the size of the United States. However, his mixed record on civil rights and exploitation of conquered territories adversely affect his reputation.\"})\n",
            "  ('French Revolution', {'url': 'https://en.wikipedia.org/wiki/French_Revolution', 'summary': 'The French Revolution was a period of political and societal change in France that began with the Estates General of 1789, and ended with the coup of 18 Brumaire on November 1799 and the formation of the French Consulate. Many of its ideas are considered fundamental principles of liberal democracy, while its values and institutions remain central to modern French political discourse.The causes are generally agreed to be a combination of social, political and economic factors, which the Ancien Régime proved unable to manage. A financial crisis and widespread social distress led, in May 1789, to the convocation of the Estates General which was converted into a National Assembly in June. The Storming of the Bastille on 14 July led to a series of radical measures by the Assembly, among them the abolition of feudalism, state control over the Catholic Church in France, and a declaration of rights.\\nThe next three years were dominated by the struggle for political control, exacerbated by economic depression. A series of military defeats following the outbreak of the French Revolutionary Wars in April 1792 resulted in the Insurrection of 10 August 1792. The monarchy was abolished and replaced by the French First Republic in September, while Louis XVI was executed in January 1793.\\nAfter another Paris-based revolt in June 1793, the constitution was suspended and effective political power passed from the National Convention to the Committee of Public Safety. An estimated 16,000 were executed in the subsequent Reign of Terror, which ended in July 1794. Weakened by external threats and internal opposition, the Republic was replaced in November 1795 by the Directory (1795–1799). Four years later in November 1799, the Consulate seized power in a military coup led by Napoleon Bonaparte. This is generally seen as marking the end of the Revolutionary period.'})\n",
            "  ('France', {'url': 'https://en.wikipedia.org/wiki/France', 'summary': \"France (French: [fʁɑ̃s] ), officially the French Republic (French: République française [ʁepyblik fʁɑ̃sɛːz]), is a country located primarily in Western Europe. It also includes overseas regions and territories in the Americas and the Atlantic, Pacific and Indian oceans, giving it one of the largest discontiguous exclusive economic zones in the world. Metropolitan France shares borders with Belgium and Luxembourg to the north, Germany to the north east, Switzerland to the east, Italy and Monaco to the south east, Andorra and Spain to the south, and a maritime border with the United Kingdom to the north west. Its metropolitan area extends from the Rhine to the Atlantic Ocean and from the Mediterranean Sea to the English Channel and the North Sea. Its overseas territories include French Guiana in South America, Saint Pierre and Miquelon in the North Atlantic, the French West Indies, and many islands in Oceania and the Indian Ocean. Its eighteen integral regions (five of which are overseas) span a combined area of 643,801 km2 (248,573 sq mi) and have a total population of over 68 million as of January 2023. France is a unitary semi-presidential republic with its capital in Paris, the country's largest city and main cultural and commercial centre; other major urban areas include Marseille, Lyon, Toulouse, Lille, Bordeaux, Strasbourg, and Nice.\\nMetropolitan France was settled during the Iron Age by Celtic tribes known as Gauls before Rome annexed the area in 51 BC, leading to a distinct Gallo-Roman culture. In the Early Middle Ages, the Germanic Franks formed the Kingdom of Francia, which became the heartland of the Carolingian Empire. The Treaty of Verdun of 843 partitioned the empire, with West Francia evolving into the Kingdom of France. In the High Middle Ages, France was a powerful but decentralized feudal kingdom, but from the mid-14th to the mid-15th centuries, France was plunged into a dynastic conflict with England known as the Hundred Years' War. In the 16th century, the French Renaissance saw culture flourish and a French colonial empire rise. Internally, France was dominated by the conflict with the House of Habsburg and the French Wars of Religion between Catholics and Huguenots. France was successful in the Thirty Years' War and further increased its influence during the reign of Louis XIV.The French Revolution of 1789 overthrew the Ancien Régime and produced the Declaration of the Rights of Man, which expresses the nation's ideals to this day. France reached its political and military zenith in the early 19th century under Napoleon Bonaparte, subjugating part of continental Europe and establishing the First French Empire. The French Revolutionary and Napoleonic Wars significantly shaped the course of European history. The collapse of the empire initiated a period of relative decline, in which France endured a tumultuous succession of governments until the founding of the French Third Republic during the Franco-Prussian War in 1870. Subsequent decades saw a period of economic prosperity and cultural and scientific flourishing known as the Belle Époque. France was one of the major participants of World War I, from which it emerged victorious at great human and economic cost. It was among the Allied powers of World War II, but it surrendered and was occupied by the Axis in 1940. Following its liberation in 1944, the short-lived Fourth Republic was established and later dissolved in the course of the defeat in the Algerian War. The current Fifth Republic was formed in 1958 by Charles de Gaulle. Algeria and most French colonies became independent in the 1960s, with the majority retaining close economic and military ties with France.\\nFrance retains its centuries-long status as a global centre of art, science, and philosophy. It hosts the third-largest number of UNESCO World Heritage Sites and is the world's leading tourist destination, receiving over 89 million foreign visitors in 2018. France is a developed country with a high nominal per capita income globally and its advanced economy ranks among the largest in the world. It is a great power in global affairs, being one of the five permanent members of the United Nations Security Council and an official nuclear-weapon state. France is a founding and leading member of the European Union and the eurozone, as well as a key member of the Group of Seven, North Atlantic Treaty Organization (NATO), Organisation for Economic Co-operation and Development (OECD), and Francophonie.\"})\n",
            "  ('Corsica', {'url': 'https://en.wikipedia.org/wiki/Corsica', 'summary': \"Corsica ( KOR-sik-ə, Upper Corsican: [ˈkorsiɡa], Southern Corsican: [ˈkɔrsika], Italian: [ˈkɔrsika]; French: Corse [kɔʁs] ; Ligurian: Còrsega) is an island in the Mediterranean Sea and one of the 18 regions of France. It is the fourth-largest island in the Mediterranean and lies southeast of the French mainland, west of the Italian Peninsula and immediately north of the Italian island of Sardinia, the nearest land mass. A single chain of mountains makes up two-thirds of the island. As of January 2023, it had a population of 351,255.The island is a territorial collectivity of France. The regional capital is Ajaccio. Although the region is divided into two administrative departments, Haute-Corse and Corse-du-Sud, their respective regional and departmental territorial collectivities were merged on 1 January 2018 to form the single territorial collectivity of Corsica. Corsican autonomy is more far reaching than other regional collectives of France and the Corsican Assembly is permitted to exercise limited executive powers. Corsica's second-largest town is Bastia, the prefecture of Haute-Corse.\\nCorsica was ruled by the Republic of Genoa from 1284 to 1755, when it seceded to become a self-proclaimed, Italian-speaking Republic. In 1768, Genoa officially ceded it to Louis XV of France as part of a pledge for the debts incurred after enlisting French military help in suppressing the Corsican revolt; as a result France annexed the island in 1769. The future Emperor of the French, Napoleon Bonaparte, was a native Corsican, born that same year in Ajaccio: his ancestral home, Maison Bonaparte, is now a visitor attraction and museum. Because of Corsica's historical ties to Tuscany, the island has retained many Italian cultural elements and many Corsican surnames are rooted in the Italian peninsula. \\nFrench (Français) is the official and most widely spoken language on the island. Corsican, the native tongue and an Italo-Dalmatian language, is recognized as one of France's regional languages. Italian is also widely spoken. \\nCorsica is the third-least populated region of France after Mayotte and French Guiana.\"})\n",
            "  ('French Directory', {'url': 'https://en.wikipedia.org/wiki/French_Directory', 'summary': 'The Directory (also called Directorate, French: le Directoire) was the governing five-member committee in the French First Republic from 26 October 1795 (4 Brumaire an IV) until 10 November 1799, when it was overthrown by Napoleon Bonaparte in the Coup of 18 Brumaire and replaced by the Consulate. Directoire is the name of the final four years of the French Revolution. Mainstream historiography also uses the term in reference to the period from the dissolution of the National Convention on 26 October 1795 to Napoleon\\'s coup d’état.\\nThe Directory was continually at war with foreign coalitions, including Britain, Austria, Prussia, the Kingdom of Naples, Russia and the Ottoman Empire. It annexed Belgium and the left bank of the Rhine, while Bonaparte conquered a large part of Italy. The Directory established 29 short-lived sister republics in Italy, Switzerland and the Netherlands. The conquered cities and states were required to send France huge amounts of money, as well as art treasures, which were used to fill the new Louvre museum in Paris. An army led by Bonaparte tried to conquer Egypt and marched as far as Saint-Jean-d\\'Acre in Syria. The Directory defeated a resurgence of the War in the Vendée, the royalist-led civil war in the Vendée region, but failed in its venture to support the Irish Rebellion of 1798 and create an Irish Republic.\\nThe French economy was in continual crisis during the Directory. At the beginning, the treasury was empty; the paper money, the Assignat, had fallen to a fraction of its value, and prices soared. The Directory stopped printing assignats and restored the value of the money, but this caused a new crisis; prices and wages fell, and economic activity slowed to a standstill.\\nIn its first two years, the Directory concentrated on ending the excesses of the Jacobin Reign of Terror; mass executions stopped, and measures taken against exiled priests and royalists were relaxed. The Jacobin political club was closed on 12 November 1794 and the government crushed an armed uprising planned by the Jacobins and an early socialist revolutionary, François-Noël Babeuf, known as \"Gracchus Babeuf\". But after the discovery of a royalist conspiracy including a prominent general, Jean-Charles Pichegru, the Jacobins took charge of the new Councils and hardened the measures against the Church and émigrés. They took two additional seats in the Directory, hopelessly dividing it.\\nIn 1799, after several defeats, French victories in the Netherlands and Switzerland restored the French military position, but the Directory had lost all the political factions\\' support, including some of its Directors. Bonaparte returned from Egypt in October, and was engaged by Abbé Sieyès and others to carry out a parliamentary coup d\\'état on 9–10 November 1799. The coup abolished the Directory and replaced it with the French Consulate led by Bonaparte.'})\n",
            "  ('War of the Fourth Coalition', {'url': 'https://en.wikipedia.org/wiki/War_of_the_Fourth_Coalition', 'summary': \"The War of the Fourth Coalition (French: Guerre de la Quatrième Coalition) was a war spanning 1806-1807 that saw a multinational coalition fight against Napoleon's French Empire, subsequently being defeated. The main coalition partners were Prussia and Russia with Saxony, Sweden, and Great Britain also contributing. Excluding Prussia, some members of the coalition had previously been fighting France as part of the Third Coalition, and there was no intervening period of general peace. On 9 October 1806, Prussia declared war on France and joined a renewed coalition, fearing the rise in French power after the defeat of Austria and establishment of the French-sponsored Confederation of the Rhine in addition to having learned of French plans to cede Prussian-desired Hanover to Britain in exchange for peace. Prussia and Russia mobilized for a fresh campaign with Prussia massing troops in Saxony.Napoleon decisively defeated the Prussians in an expeditious campaign that culminated at the Battle of Jena–Auerstedt on 14 October 1806. French forces under Napoleon occupied Prussia, pursued the remnants of the shattered Prussian Army, and captured Berlin. They then advanced all the way to East Prussia, Poland and the Russian frontier, where they fought an inconclusive battle against the Russians at the Battle of Eylau on 7–8 February 1807. Napoleon's advance on the Russian frontier was briefly checked during the spring as he revitalized his army with fresh supplies. Russian forces were finally crushed by the French at the Battle of Friedland on 14 June 1807, and three days later Russia asked for a truce.Through the Treaties of Tilsit in July 1807, France made peace with Russia, which agreed to join the Continental System. The treaty was particularly harsh on Prussia, however, as Napoleon demanded much of the Prussian territory along the lower Rhine west of the Elbe and in what was part of the former Polish–Lithuanian Commonwealth. Respectively, these acquisitions were incorporated into the new Kingdom of Westphalia, led by his brother Jérôme Bonaparte. He also established the Duchy of Warsaw, a Polish client state, ruled by his new ally the king of Saxony. At the end of the war, there was peace on Continental Europe with Napoleon as master of almost all of western and central continental Europe, except for Spain, Portugal, Austria and several other smaller states.\\nDespite the end of the Fourth Coalition, Britain remained at war with France. War would return to Continental Europe later in 1807, when Napoleon decided to invade Portugal in order to compel Portugal join the Continental System. A joint Franco-Spanish force invaded Britain's ally Portugal, beginning the Peninsular War where Napoleon would also invade Spain as well. A further Fifth Coalition would be assembled when Austria re-joined the conflict in 1809.\\n\\n\"})\n",
            "  ('1806', {'url': 'https://en.wikipedia.org/wiki/1806', 'summary': '1806 (MDCCCVI) was a common year starting on Wednesday of the Gregorian calendar and a common year starting on Monday of the Julian calendar, the 1806th year of the Common Era (CE) and Anno Domini (AD) designations, the 806th  year of the 2nd millennium, the 6th  year of the 19th century, and the  7th   year of the 1800s decade. As of the start of 1806, the Gregorian calendar was 12 days ahead of the Julian calendar, which remained in localized use until 1923.'})\n",
            "  ('Ulm campaign', {'url': 'https://en.wikipedia.org/wiki/Ulm_campaign', 'summary': 'The Ulm campaign was a series of French and Bavarian military maneuvers and battles to outflank and capture an Austrian army in 1805 during the War of the Third Coalition. It took place in the vicinity of and inside the Swabian city of Ulm. The French Grande Armée, led by Napoleon, had 210,000 troops organized into seven corps and hoped to knock out the Austrian army in the Danube before Russian reinforcements could arrive. Rapid marching let Napoleon conduct a large wheeling maneuver, which captured an Austrian army of 23,000 under General Mack on 20 October at Ulm. That brought the total number of Austrian prisoners-of-war in the campaign to 60,000. The campaign is by some military historians regarded as a strategic masterpiece and was influential in the development of the Schlieffen Plan in the late 19th century. Napoleon himself wrote:\\nfour months of marching about, months of fatigue and wretchedness, have proved to me that nothing is more hideous, more miserable, than war. And yet our sufferings in the Guard are not to be compared with those of the line.The victory at Ulm did not end the war since a large Russian army under Kutuzov was near Vienna to defend the city against the French. The Russians withdrew to the northeast to await reinforcements and to link up with Austrian army units. The French moved aggressively forward and captured Vienna on 12 November. On 2 December, a massive battle at Austerlitz, causing around 24.000 soldiers to die, removed Austria from the war. The resulting Peace treaty of Pressburg in late December brought the Third Coalition to an end and established Napoleonic France as the major power in Central Europe, which led to the War of the Fourth Coalition against Prussia and Russia the following year.'})\n",
            "  ('War of the Third Coalition', {'url': 'https://en.wikipedia.org/wiki/War_of_the_Third_Coalition', 'summary': \"The War of the Third Coalition (French: Guerre de la Troisième Coalition) was a European conflict spanning from 1805 to 1806. During the war, France and its client states under Napoleon I opposed an alliance, the Third Coalition, which was made up of the United Kingdom, the Austrian Empire, the Russian Empire, Naples, Sicily, and Sweden. Prussia remained neutral during the war.\\nBritain had already been at war with France following the breakdown of the Peace of Amiens and remained the only country still at war with France after the Treaty of Pressburg. From 1803 to 1805, Britain stood under constant threat of a French invasion. The Royal Navy, however, secured mastery of the seas and decisively destroyed a Franco-Spanish fleet at the Battle of Trafalgar in October 1805.\\nThe Third Coalition itself came to full fruition in 1804–05 as Napoleon's actions in Italy and Germany (notably the arrest and execution of the Duc d'Enghien) spurred Austria and Russia into joining Britain against France. The war would be determined on the continent, and the major land operations that sealed the swift French victory involved the Ulm Campaign, a large wheeling manoeuvre by the Grande Armée lasting from late August to mid-October 1805 that captured an entire Austrian army, and the decisive French victory over a combined Austro-Russian force under Alexander I of Russia at the Battle of Austerlitz in early December. Austerlitz effectively brought the Third Coalition to an end, although later there was a small side campaign against Naples, which also resulted in a decisive French victory at the Battle of Campo Tenese.\\nOn 26 December 1805, Austria and France signed the Treaty of Pressburg, which took Austria out of both the war and the Coalition, while it reinforced the earlier treaties of Campo Formio and of Lunéville between the two powers. The treaty confirmed the Austrian cession of lands in Italy to France and in Germany to Napoleon's German allies, imposed an indemnity of 40 million francs on the defeated Habsburgs, and allowed the defeated Russian troops free passage, with their arms and equipment, through hostile territories and back to their home soil. Victory at Austerlitz also prompted Napoleon to create the Confederation of the Rhine, a collection of German client states that pledged themselves to raise an army of 63,000 men. As a direct consequence of those events, the Holy Roman Empire ceased to exist when, in 1806, Francis II abdicated the Imperial throne, becoming Francis I, Emperor of Austria. Those achievements, however, did not establish a lasting peace on the continent. Austerlitz had driven neither Russia nor Britain, whose fleet protected Sicily from a French invasion, to cease fighting. Meanwhile, Prussian worries about the growing French influence in Central Europe sparked the War of the Fourth Coalition in 1806.\"})\n",
            "  ('Battle of Austerlitz', {'url': 'https://en.wikipedia.org/wiki/Battle_of_Austerlitz', 'summary': \"The Battle of Austerlitz (2 December 1805/11 Frimaire An XIV FRC), also known as the Battle of the Three Emperors, was one of the important and decisive military engagements of the Napoleonic Wars. The battle occurred near the town of Austerlitz in the Austrian Empire (modern-day Slavkov u Brna in the Czech Republic). Around 158,000 troops were involved, of which around 24,000 were killed or wounded. The battle is often cited by military historians as one of Napoleon's tactical masterpieces, in the same league as other historic military battles like Cannae or Gaugamela. The military victory of Napoleon's Grande Armée at Austerlitz brought the War of the Third Coalition to an end, with the Peace treaty of Pressburg, signed by the French and Austrians later in the month. These achievements did not establish a lasting peace on the continent. Austerlitz had driven neither Russia nor Britain, whose armies protected Sicily from a French invasion, to settle. Meanwhile, Prussian resistance against the growing power of French military invasions in Central Europe caused another war in 1806, known as the War of the Fourth Coalition.\\nAfter eliminating an Austrian army during the Ulm campaign, French forces seized Vienna in November 1805. The Austrians avoided further conflict until the arrival of the Russians, who helped increase the allied numbers. Napoleon sent his army north in pursuit of the Allies but then ordered his forces to retreat so he could feign a grave weakness to lure the Allies into thinking that they were facing a weak army, while it was in fact formidable. Napoleon gave every indication in the days preceding the engagement that the French army was in a pitiful state, even abandoning the dominant Pratzen Heights near Austerlitz. He deployed the French army below the Pratzen Heights and deliberately weakened his right flank, enticing the Allies to launch a major assault there in the hopes of rolling up the French line. A forced march from Vienna by Marshal Davout and his III Corps plugged the gap left by Napoleon just in time. Meanwhile, the heavy Allied deployment against the French right weakened the Allied center on the Pratzen Heights, which was viciously attacked by the IV Corps of Marshal Soult. With the Allied center demolished, the French swept through both enemy flanks and sent the Allies fleeing chaotically, capturing thousands of prisoners in the process.\\nThe Allied disaster significantly shook the faith of Emperor Francis II in the British-led war effort. France and Austria agreed to an armistice immediately, and the Treaty of Pressburg followed shortly after, on 26 December. Pressburg took Austria out of both the war and the Coalition while reinforcing the earlier treaties of Campo Formio and of Lunéville between the two powers. The treaty confirmed the Austrian loss of lands in Italy and Bavaria to France, and in Germany to Napoleon's German allies. It also imposed an indemnity of 40 million francs on the defeated Habsburgs and allowed the fleeing Russian troops free passage through hostile territories and back to their home soil. Critically, victory at Austerlitz permitted the creation of the Confederation of the Rhine, a collection of German states intended as a buffer zone between France and Central Europe. The Confederation rendered the Holy Roman Empire virtually useless, so the latter collapsed in 1806 after Francis abdicated the imperial throne. These achievements, however, did not establish a lasting peace on the continent. Prussian worries about the growing French influence in Central Europe sparked the War of the Fourth Coalition in 1806.\"})\n",
            "  ('1805', {'url': 'https://en.wikipedia.org/wiki/1805', 'summary': '1805 (MDCCCV) was a common year starting on Tuesday of the Gregorian calendar and a common year starting on Sunday of the Julian calendar, the 1805th year of the Common Era (CE) and Anno Domini (AD) designations, the 805th  year of the 2nd millennium, the 5th  year of the 19th century, and the  6th   year of the 1800s decade. As of the start of 1805, the Gregorian calendar was 12 days ahead of the Julian calendar, which remained in localized use until 1923.   After thirteen years the First French Empire abolished the French Republican Calendar in favour of the Gregorian calendar.'})\n",
            "  ('Battle of Wagram', {'url': 'https://en.wikipedia.org/wiki/Battle_of_Wagram', 'summary': \"The Battle of Wagram ([ˈvaɡram]; 5–6 July 1809) was a military engagement of the Napoleonic Wars that ended in a costly but decisive victory for Emperor Napoleon's French and allied army against the Austrian army under the command of Archduke Charles of Austria-Teschen. The battle led to the breakup of the Fifth Coalition, the Austrian and British-led alliance against France. Wagram was the largest battle in European history up to its time.\\nIn 1809, the French military presence in the Confederation of the Rhine was diminished as Napoleon transferred a number of soldiers to fight in the Peninsular War. As a result, the Austrian Empire saw its chance to recover some of its former sphere of influence and invaded the Kingdom of Bavaria, a French ally. Recovering from his initial surprise, Napoleon beat the Austrian forces and occupied Vienna at the beginning of May 1809. Despite the string of sharp defeats and the loss of the empire's capital, Archduke Charles salvaged an army, with which he retreated north of the Danube. This allowed the Austrians to continue the war.  Towards the end of May, Napoleon resumed the offensive, suffering a surprise defeat at the Battle of Aspern-Essling.\\nIt took Napoleon six weeks to prepare his next offensive, for which he amassed a 172,000-man French, German and Italian army in the vicinity of Vienna. The Battle of Wagram began after Napoleon crossed the Danube with the bulk of these forces during the night of 4 July and attacked the 136,000-man strong Austrian army. Having successfully crossed the river, Napoleon attempted an early breakthrough and launched a series of evening attacks against the Austrian army. The Austrians were thinly spread in a wide semicircle, but held a naturally strong position. After the attackers enjoyed some initial success, the defenders regained the upper hand and the attacks failed. Bolstered by his success, the next day at dawn Archduke Charles launched a series of attacks along the entire battle line, seeking to take the opposing army in a double envelopment. The offensive failed against the French right but nearly broke Napoleon's left. However, the Emperor countered by launching a cavalry charge, which temporarily halted the Austrian advance. He then redeployed IV Corps to stabilise his left, while setting up a grand battery, which pounded the Austrian right and centre. The tide of battle turned and the Emperor launched an offensive along the entire line, while Maréchal Louis-Nicolas Davout drove an offensive, which turned the Austrian left, and rendered Charles's position untenable. Towards mid-afternoon on 6 July, Charles admitted defeat and led a retreat, frustrating enemy attempts to pursue. After the battle, Charles remained in command of a cohesive force and decided to retreat to Bohemia. However, the Grande Armée eventually caught up with him and scored a victory at the Battle of Znaim. With the battle still raging, Charles decided to ask for an armistice, effectively ending the war.\\nWith 74,000 casualties, the two-day battle of Wagram was particularly bloody, mainly due to the use of 800 artillery pieces and the expenditure of 200,000 rounds of artillery ammunition on a flat battlefield packed with some 300,000 men. Although Napoleon was the uncontested winner, he failed to secure an overwhelming victory and the Austrian casualties were only slightly greater than those of the French and allies. Nonetheless, the defeat was serious enough to shatter the morale of the Austrians, who could no longer find the will to continue the struggle. The resulting Treaty of Schönbrunn meant the loss of one sixth of the Austrian Empire's subjects, along with some territories, rendering it landlocked until the German Campaign of 1813.\\nAfter the battle, Emperor Napoleon bestowed to Louis-Alexandre Berthier, who was his Marshal, Chief of Staff, Minister of War and Vice-Constable of the Empire, the victory title of 1st Prince of Wagram, making him an official member of the French nobility. Berthier had previously been granted the title of Sovereign Prince of Neuchâtel and the Prince of Valangin in 1806. This allowed his descendants to carry the titles of Prince and Princess of Wagram.\"})\n",
            "  ('War of the Fifth Coalition', {'url': 'https://en.wikipedia.org/wiki/War_of_the_Fifth_Coalition', 'summary': \"The War of the Fifth Coalition (French: Guerre de la Cinquième Coalition) was a European conflict in 1809 that was part of the Napoleonic Wars and the Coalition Wars.  The main conflict took place in central Europe between the Austrian Empire of Francis I and Napoleon's French Empire. The French were supported by their client states—the Kingdom of Italy, the Confederation of the Rhine and the Duchy of Warsaw. Austria was supported by the Fifth Coalition which included the United Kingdom, Portugal, Spain, and the Kingdoms of Sardinia and Sicily, although the latter two took no part in the fighting. By the start of 1809 much of the French army was committed to the Peninsular War against Britain, Spain and Portugal. After France withdrew 108,000 soldiers from Germany, Austria attacked France to seek the recovery of territories lost in the 1803–1806 War of the Third Coalition. The Austrians hoped Prussia would support them, having recently been defeated by France, but Prussia chose to remain neutral.\\nOn 10 April 1809 Austrian forces under Archduke Charles crossed the border of Bavaria, a French client state. The French response, under Louis-Alexandre Berthier, was disorganised but order was imposed with the arrival of Napoleon on 17 April. Napoleon led an advance to Landshut, hoping to cut off the Austrian line of retreat and sweep into their rear. Charles crossed the Danube at Regensburg, which allowed him to retreat eastwards, although he failed to reach the Austrian capital, Vienna, before the French. A French assault across the Danube was repulsed on 21–22 May at the Battle of Aspern-Essling but a repeat attack was successful in July. Napoleon won a major victory at the 5–6 July Battle of Wagram, which forced the Austrians to sign the Armistice of Znaim on 12 July. Austrian invasions of the Duchy of Warsaw and Saxony (where they fought alongside the Black Brunswickers) were repulsed and they were driven out of their territories in Italy. British forces landed in Walcheren, in the French client state of Holland, but were unable to seize their objective of capturing Antwerp and were later withdrawn.\\nThe war ended with the Treaty of Schönbrunn, which was regarded as harsh towards Austria as she lost her Mediterranean ports and 20% of her population. Despite the eventual French victory, their defeat at Aspern-Essling showed that Napoleon could be defeated on the battlefield. The war led to the Tyrolean Rebellion, the 1809 Gottscheer rebellion and rebellions in Italy which, although suppressed, foreshadowed future nationalist and anti-French risings. After Schönbrunn, Austria became a French ally and this was cemented by the marriage of Napoleon to the Austrian princess Marie Louise.\"})\n",
            "  ('War of the Sixth Coalition', {'url': 'https://en.wikipedia.org/wiki/War_of_the_Sixth_Coalition', 'summary': 'In the War of the Sixth Coalition (French: Guerre de la Sixième Coalition) (March 1813 – May 1814), sometimes known in Germany as the Wars of Liberation (German: Befreiungskriege), a coalition of Austria, Prussia, Russia, Spain, the United Kingdom, Portugal, Sweden, Sardinia, and a number of German States defeated France and drove Napoleon into exile on Elba.  After the disastrous French invasion of Russia of 1812 in which they had been forced to support France, Prussia and Austria joined Russia, the United Kingdom, Sweden, and Portugal, and the rebels in Spain who were already at war with France.\\nThe War of the Sixth Coalition saw major battles at Lützen, Bautzen, and Dresden. The even larger Battle of Leipzig (also known as the Battle of Nations) was the largest battle in European history before World War I. Ultimately, Napoleon\\'s earlier setbacks in Spain, Portugal and Russia proved to be the seeds of his undoing. With their armies reorganized, the allies drove Napoleon out of Germany in 1813 and invaded France in 1814. The Allies defeated the remaining French armies, occupied Paris, and forced Napoleon to abdicate and go into exile. The French monarchy was revived by the allies, who handed rule to the heir of the House of Bourbon in the Bourbon Restoration.\\nThe \"Hundred Days\" War of the Seventh Coalition was triggered in 1815 when Napoleon escaped from his captivity on Elba and returned to power in France.  He was defeated again for the final time at Waterloo, ending the Napoleonic Wars.'})\n",
            "  ('1813', {'url': 'https://en.wikipedia.org/wiki/1813', 'summary': '1813 (MDCCCXIII) was a common year starting on Friday of the Gregorian calendar and a common year starting on Wednesday of the Julian calendar, the 1813th year of the Common Era (CE) and Anno Domini (AD) designations, the 813th  year of the 2nd millennium, the 13th  year of the 19th century, and the  4th   year of the 1810s decade. As of the start of 1813, the Gregorian calendar was 12 days ahead of the Julian calendar, which remained in localized use until 1923.'})\n",
            "  ('Hundred Days', {'url': 'https://en.wikipedia.org/wiki/Hundred_Days', 'summary': \"The Hundred Days (French: les Cent-Jours IPA: [le sɑ̃ ʒuʁ]),  also known as the War of the Seventh Coalition (French: Guerre de la Septième Coalition), marked the period between Napoleon's return from eleven months of exile on the island of Elba to Paris on 20 March 1815 and the second restoration of King Louis XVIII on 8 July 1815 (a period of 110 days). This period saw the War of the Seventh Coalition, and includes the Waterloo Campaign, the Neapolitan War as well as several other minor campaigns. The phrase les Cent Jours (the hundred days) was first used by the prefect of Paris, Gaspard, comte de Chabrol, in his speech welcoming the king back to Paris on 8 July.Napoleon returned while the Congress of Vienna was sitting. On 13 March, seven days before Napoleon reached Paris, the powers at the Congress of Vienna declared him an outlaw, and on 25 March Austria, Prussia, Russia and the United Kingdom, the four Great Powers and key members of the Seventh Coalition, bound themselves to put 150,000 men each into the field to end his rule. This set the stage for the last conflict in the Napoleonic Wars, the defeat of Napoleon at the Battle of Waterloo, the second restoration of the French kingdom, and the permanent exile of Napoleon to the distant island of Saint Helena, where he died of stomach cancer in May 1821.\"})\n",
            "  ('Battle of Waterloo', {'url': 'https://en.wikipedia.org/wiki/Battle_of_Waterloo', 'summary': 'The Battle of Waterloo (Dutch pronunciation: [ˈʋaːtərloː] ) was fought on Sunday 18 June 1815, near Waterloo (at that time in the United Kingdom of the Netherlands, now in Belgium), marking  the end of the Napoleonic Wars. A French army under the command of Napoleon was defeated by two armies of the Seventh Coalition. One of these was a British-led force with units from the United Kingdom, the Netherlands, Hanover, Brunswick, and Nassau, under the command of the Duke of Wellington (often referred to as the Anglo-allied army or Wellington\\'s army). The other comprised three corps of the Prussian army under Field Marshal von Blücher (the fourth corps of this army fought at the Battle of Wavre on the same day). The battle was known contemporarily as the Battle of Mont Saint-Jean in France or La Belle Alliance (\"the Beautiful Alliance\") in Prussia.Upon Napoleon\\'s return to power in March 1815 (beginning the Hundred Days), many states that had previously opposed him formed the Seventh Coalition and hurriedly mobilised their armies. Wellington\\'s and Blücher\\'s armies were cantoned close to the northeastern border of France. Napoleon planned to attack them separately, before they could link up and invade France with other members of the coalition.\\nOn 16 June, Napoleon successfully attacked the bulk of the Prussian army at the Battle of Ligny with his main force, while a small portion of the French army contested the Battle of Quatre Bras to prevent the Anglo-allied army from reinforcing the Prussians. The Anglo-allied army held their ground at Quatre Bras, and on the 17th, the Prussians withdrew from Ligny in good order, while Wellington then withdrew in parallel with the Prussians northward to Waterloo on 17 June. Napoleon sent a third of his forces to pursue the Prussians, which resulted in the separate Battle of Wavre with the Prussian rear-guard on 18–19 June, and prevented that French force from participating at Waterloo.\\nUpon learning that the Prussian army was able to support him, Wellington decided to offer battle on the Mont-Saint-Jean escarpment across the Brussels road, near the village of Waterloo. Here he withstood repeated attacks by the French throughout the afternoon of 18 June and almost lost the battle, but was eventually aided by the progressively arriving 50,000 Prussians who attacked the French flank and inflicted heavy casualties. In the evening, Napoleon assaulted the Anglo-allied line with his last reserves, the senior infantry battalions of the Imperial Guard. With the Prussians breaking through on the French right flank, the Anglo-allied army repulsed the Imperial Guard, and the French army was routed.\\nWaterloo was the decisive engagement of the Waterloo campaign and Napoleon\\'s last. It was also the second bloodiest single day battle of the Napoleonic Wars, after Borodino. According to Wellington, the battle was \"the nearest-run thing you ever saw in your life\". Napoleon abdicated four days later, and coalition forces entered Paris on 7 July. The defeat at Waterloo marked the end of Napoleon\\'s Hundred Days return from exile. It precipitated Napoleon\\'s second and definitive abdication as Emperor of the French, and ended the First French Empire. It set a historical  milestone between serial European wars and decades of relative peace, often referred to as the Pax Britannica.  In popular culture, the phrase \"meeting one\\'s Waterloo\" has become an expression for someone suffering a final defeat, as in the ABBA song \"Waterloo\".\\nThe battlefield is located in the Belgian municipalities of Braine-l\\'Alleud and Lasne, about 15 kilometres (9.3 mi) south of Brussels, and about 2 kilometres (1.2 mi) from the town of Waterloo. The site of the battlefield today is dominated by the monument of the Lion\\'s Mound, a large artificial hill constructed from earth taken from the battlefield itself, but the topography of the battlefield near the mound has not been preserved.\\n\\n'})\n",
            "Relations:\n",
            "  {'head': 'Napoleon', 'type': 'participant in', 'tail': 'French Revolution', 'meta': {'spans': [[0, 128], [119, 247]]}}\n",
            "  {'head': 'French Revolution', 'type': 'participant', 'tail': 'Napoleon', 'meta': {'spans': [[0, 128]]}}\n",
            "  {'head': 'French Revolution', 'type': 'country', 'tail': 'France', 'meta': {'spans': [[0, 128]]}}\n",
            "  {'head': 'Napoleon', 'type': 'place of birth', 'tail': 'Corsica', 'meta': {'spans': [[119, 247]]}}\n",
            "  {'head': 'French Directory', 'type': 'facet of', 'tail': 'French Revolution', 'meta': {'spans': [[119, 247]]}}\n",
            "  {'head': 'War of the Fourth Coalition', 'type': 'start time', 'tail': '1806', 'meta': {'spans': [[238, 366]]}}\n",
            "  {'head': 'Ulm campaign', 'type': 'part of', 'tail': 'War of the Third Coalition', 'meta': {'spans': [[238, 366]]}}\n",
            "  {'head': 'Battle of Austerlitz', 'type': 'part of', 'tail': 'War of the Third Coalition', 'meta': {'spans': [[238, 366]]}}\n",
            "  {'head': 'War of the Third Coalition', 'type': 'start time', 'tail': '1805', 'meta': {'spans': [[238, 366]]}}\n",
            "  {'head': 'Battle of Wagram', 'type': 'part of', 'tail': 'War of the Fifth Coalition', 'meta': {'spans': [[357, 485]]}}\n",
            "  {'head': 'War of the Fourth Coalition', 'type': 'followed by', 'tail': 'War of the Fifth Coalition', 'meta': {'spans': [[357, 485]]}}\n",
            "  {'head': 'War of the Sixth Coalition', 'type': 'start time', 'tail': '1813', 'meta': {'spans': [[476, 604]]}}\n",
            "  {'head': 'Hundred Days', 'type': 'has part', 'tail': 'Battle of Waterloo', 'meta': {'spans': [[595, 723]]}}\n",
            "  {'head': 'Battle of Waterloo', 'type': 'part of', 'tail': 'Hundred Days', 'meta': {'spans': [[595, 723]]}}\n"
          ]
        }
      ],
      "source": [
        "text = \"\"\"\n",
        "Napoleon Bonaparte (born Napoleone di Buonaparte; 15 August 1769 – 5 May 1821), and later known by his regnal name Napoleon I, was a French military and political leader who rose to prominence during the French Revolution and led several successful campaigns during the Revolutionary Wars. He was the de facto leader of the French Republic as First Consul from 1799 to 1804. As Napoleon I, he was Emperor of the French from 1804 until 1814 and again in 1815. Napoleon's political and cultural legacy has endured, and he has been one of the most celebrated and controversial leaders in world history. Napoleon was born on the island of Corsica not long after its annexation by the Kingdom of France.[5] He supported the French Revolution in 1789 while serving in the French army, and tried to spread its ideals to his native Corsica. He rose rapidly in the Army after he saved the governing French Directory by firing on royalist insurgents. In 1796, he began a military campaign against the Austrians and their Italian allies, scoring decisive victories and becoming a national hero. Two years later, he led a military expedition to Egypt that served as a springboard to political power. He engineered a coup in November 1799 and became First Consul of the Republic. Differences with the British meant that the French faced the War of the Third Coalition by 1805. Napoleon shattered this coalition with victories in the Ulm Campaign, and at the Battle of Austerlitz, which led to the dissolving of the Holy Roman Empire. In 1806, the Fourth Coalition took up arms against him because Prussia became worried about growing French influence on the continent. Napoleon knocked out Prussia at the battles of Jena and Auerstedt, marched the Grande Armée into Eastern Europe, annihilating the Russians in June 1807 at Friedland, and forcing the defeated nations of the Fourth Coalition to accept the Treaties of Tilsit. Two years later, the Austrians challenged the French again during the War of the Fifth Coalition, but Napoleon solidified his grip over Europe after triumphing at the Battle of Wagram. Hoping to extend the Continental System, his embargo against Britain, Napoleon invaded the Iberian Peninsula and declared his brother Joseph King of Spain in 1808. The Spanish and the Portuguese revolted in the Peninsular War, culminating in defeat for Napoleon's marshals. Napoleon launched an invasion of Russia in the summer of 1812. The resulting campaign witnessed the catastrophic retreat of Napoleon's Grande Armée. In 1813, Prussia and Austria joined Russian forces in a Sixth Coalition against France. A chaotic military campaign resulted in a large coalition army defeating Napoleon at the Battle of Leipzig in October 1813. The coalition invaded France and captured Paris, forcing Napoleon to abdicate in April 1814. He was exiled to the island of Elba, between Corsica and Italy. In France, the Bourbons were restored to power. However, Napoleon escaped Elba in February 1815 and took control of France.[6][7] The Allies responded by forming a Seventh Coalition, which defeated Napoleon at the Battle of Waterloo in June 1815. The British exiled him to the remote island of Saint Helena in the Atlantic, where he died in 1821 at the age of 51. Napoleon had an extensive impact on the modern world, bringing liberal reforms to the many countries he conquered, especially the Low Countries, Switzerland, and parts of modern Italy and Germany. He implemented liberal policies in France and Western Europe.\n",
        "\"\"\"\n",
        "\n",
        "kb = from_text_to_kb(text)\n",
        "kb.print()\n",
        "# Entities:\n",
        "#  ('Napoleon', {'url': 'https://en.wikipedia.org/wiki/Napoleon',\n",
        "#   'summary': \"Napoleon Bonaparte (born Napoleone di Buonaparte; 15 August ...\"})\n",
        "#  ('French Revolution', {'url': 'https://en.wikipedia.org/wiki/French_Revolution',\n",
        "#   'summary': 'The French Revolution (French: Révolution française...\"})\n",
        "#  ...\n",
        "# Relations:\n",
        "#  {'head': 'Napoleon', 'type': 'participant in', 'tail': 'French Revolution',\n",
        "#   'meta': {'spans': [[0, 128], [119, 247]]}}\n",
        "#  {'head': 'French Revolution', 'type': 'participant', 'tail': 'Napoleon',\n",
        "#   'meta': {'spans': [[0, 128]]}}\n",
        "#  ..."
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "vyoNA7edwUfJ"
      },
      "source": [
        "# 从网络文章中提取 KB"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 46,
      "metadata": {
        "id": "WwQa99fCXHEN"
      },
      "outputs": [],
      "source": [
        "def from_text_to_kb(text, article_url, span_length=128, article_title=None,\n",
        "                    article_publish_date=None, verbose=False):\n",
        "    # tokenize whole text\n",
        "    inputs = tokenizer([text], return_tensors=\"pt\")\n",
        "\n",
        "    # compute span boundaries\n",
        "    num_tokens = len(inputs[\"input_ids\"][0])\n",
        "    if verbose:\n",
        "        print(f\"Input has {num_tokens} tokens\")\n",
        "    num_spans = math.ceil(num_tokens / span_length)\n",
        "    if verbose:\n",
        "        print(f\"Input has {num_spans} spans\")\n",
        "    overlap = math.ceil((num_spans * span_length - num_tokens) /\n",
        "                        max(num_spans - 1, 1))\n",
        "    spans_boundaries = []\n",
        "    start = 0\n",
        "    for i in range(num_spans):\n",
        "        spans_boundaries.append([start + span_length * i,\n",
        "                                 start + span_length * (i + 1)])\n",
        "        start -= overlap\n",
        "    if verbose:\n",
        "        print(f\"Span boundaries are {spans_boundaries}\")\n",
        "\n",
        "    # transform input with spans\n",
        "    tensor_ids = [inputs[\"input_ids\"][0][boundary[0]:boundary[1]]\n",
        "                  for boundary in spans_boundaries]\n",
        "    tensor_masks = [inputs[\"attention_mask\"][0][boundary[0]:boundary[1]]\n",
        "                    for boundary in spans_boundaries]\n",
        "    inputs = {\n",
        "        \"input_ids\": torch.stack(tensor_ids),\n",
        "        \"attention_mask\": torch.stack(tensor_masks)\n",
        "    }\n",
        "\n",
        "    # generate relations\n",
        "    num_return_sequences = 3\n",
        "    gen_kwargs = {\n",
        "        \"max_length\": 256,\n",
        "        \"length_penalty\": 0,\n",
        "        \"num_beams\": 3,\n",
        "        \"num_return_sequences\": num_return_sequences\n",
        "    }\n",
        "    generated_tokens = model.generate(\n",
        "        **inputs,\n",
        "        **gen_kwargs,\n",
        "    )\n",
        "\n",
        "    # decode relations\n",
        "    decoded_preds = tokenizer.batch_decode(generated_tokens,\n",
        "                                           skip_special_tokens=False)\n",
        "\n",
        "    # create kb\n",
        "    kb = KB()\n",
        "    i = 0\n",
        "    for sentence_pred in decoded_preds:\n",
        "        current_span_index = i // num_return_sequences\n",
        "        relations = extract_relations_from_model_output(sentence_pred)\n",
        "        for relation in relations:\n",
        "            relation[\"meta\"] = {\n",
        "                article_url: {\n",
        "                    \"spans\": [spans_boundaries[current_span_index]]\n",
        "                }\n",
        "            }\n",
        "            kb.add_relation(relation, article_title, article_publish_date)\n",
        "        i += 1\n",
        "\n",
        "    return kb"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "ZmEGrg15U8hX"
      },
      "outputs": [],
      "source": [
        "class KB():\n",
        "    def __init__(self):\n",
        "        self.entities = {} # { entity_title: {...} }\n",
        "        self.relations = [] # [ head: entity_title, type: ..., tail: entity_title,\n",
        "          # meta: { article_url: { spans: [...] } } ]\n",
        "        self.sources = {} # { article_url: {...} }\n",
        "\n",
        "    def merge_with_kb(self, kb2):\n",
        "        for r in kb2.relations:\n",
        "            article_url = list(r[\"meta\"].keys())[0]\n",
        "            source_data = kb2.sources[article_url]\n",
        "            self.add_relation(r, source_data[\"article_title\"],\n",
        "                              source_data[\"article_publish_date\"])\n",
        "\n",
        "    def are_relations_equal(self, r1, r2):\n",
        "        return all(r1[attr] == r2[attr] for attr in [\"head\", \"type\", \"tail\"])\n",
        "\n",
        "    def exists_relation(self, r1):\n",
        "        return any(self.are_relations_equal(r1, r2) for r2 in self.relations)\n",
        "\n",
        "    def merge_relations(self, r2):\n",
        "        r1 = [r for r in self.relations\n",
        "              if self.are_relations_equal(r2, r)][0]\n",
        "\n",
        "        # if different article\n",
        "        article_url = list(r2[\"meta\"].keys())[0]\n",
        "        if article_url not in r1[\"meta\"]:\n",
        "            r1[\"meta\"][article_url] = r2[\"meta\"][article_url]\n",
        "\n",
        "        # if existing article\n",
        "        else:\n",
        "            spans_to_add = [span for span in r2[\"meta\"][article_url][\"spans\"]\n",
        "                            if span not in r1[\"meta\"][article_url][\"spans\"]]\n",
        "            r1[\"meta\"][article_url][\"spans\"] += spans_to_add\n",
        "\n",
        "    def get_wikipedia_data(self, candidate_entity):\n",
        "        try:\n",
        "            page = wikipedia.page(candidate_entity, auto_suggest=False)\n",
        "            entity_data = {\n",
        "                \"title\": page.title,\n",
        "                \"url\": page.url,\n",
        "                \"summary\": page.summary\n",
        "            }\n",
        "            return entity_data\n",
        "        except:\n",
        "            return None\n",
        "\n",
        "    def add_entity(self, e):\n",
        "        self.entities[e[\"title\"]] = {k:v for k,v in e.items() if k != \"title\"}\n",
        "\n",
        "    def add_relation(self, r, article_title, article_publish_date):\n",
        "        # check on wikipedia\n",
        "        candidate_entities = [r[\"head\"], r[\"tail\"]]\n",
        "        entities = [self.get_wikipedia_data(ent) for ent in candidate_entities]\n",
        "\n",
        "        # if one entity does not exist, stop\n",
        "        if any(ent is None for ent in entities):\n",
        "            return\n",
        "\n",
        "        # manage new entities\n",
        "        for e in entities:\n",
        "            self.add_entity(e)\n",
        "\n",
        "        # rename relation entities with their wikipedia titles\n",
        "        r[\"head\"] = entities[0][\"title\"]\n",
        "        r[\"tail\"] = entities[1][\"title\"]\n",
        "\n",
        "        # add source if not in kb\n",
        "        article_url = list(r[\"meta\"].keys())[0]\n",
        "        if article_url not in self.sources:\n",
        "            self.sources[article_url] = {\n",
        "                \"article_title\": article_title,\n",
        "                \"article_publish_date\": article_publish_date\n",
        "            }\n",
        "\n",
        "        # manage new relation\n",
        "        if not self.exists_relation(r):\n",
        "            self.relations.append(r)\n",
        "        else:\n",
        "            self.merge_relations(r)\n",
        "\n",
        "    def print(self):\n",
        "        print(\"Entities:\")\n",
        "        for e in self.entities.items():\n",
        "            print(f\"  {e}\")\n",
        "        print(\"Relations:\")\n",
        "        for r in self.relations:\n",
        "            print(f\"  {r}\")\n",
        "        print(\"Sources:\")\n",
        "        for s in self.sources.items():\n",
        "            print(f\"  {s}\")"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "QFuxO4lfyibl"
      },
      "outputs": [],
      "source": [
        "def get_article(url):\n",
        "    article = Article(url)\n",
        "    article.download()\n",
        "    article.parse()\n",
        "    return article\n",
        "\n",
        "def from_url_to_kb(url):\n",
        "    article = get_article(url)\n",
        "    config = {\n",
        "        \"article_title\": article.title,\n",
        "        \"article_publish_date\": article.publish_date\n",
        "    }\n",
        "    kb = from_text_to_kb(article.text, article.url, **config)\n",
        "    return kb"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "jJMwkOWCwj5T",
        "outputId": "ba75e59f-424d-4bdb-9745-db9da44068d1"
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Entities:\n",
            "  ('MicroStrategy', {'url': 'https://en.wikipedia.org/wiki/MicroStrategy', 'summary': \"MicroStrategy Incorporated is an American company that provides business intelligence (BI), mobile software, and cloud-based services. Founded in 1989 by Michael J. Saylor, Sanju Bansal, and Thomas Spahr, the firm develops software to analyze internal and external data in order to make business decisions and to develop mobile apps. It is a public company headquartered in Tysons Corner, Virginia, in the Washington metropolitan area. Its primary business analytics competitors include SAP AG Business Objects, IBM Cognos, and Oracle Corporation's BI Platform. Saylor is the Executive Chairman and, from 1989 to 2022, was the CEO.\"})\n",
            "  ('Michael J. Saylor', {'url': 'https://en.wikipedia.org/wiki/Michael_J._Saylor', 'summary': \"Michael J. Saylor (born February 4, 1965) is an American entrepreneur and business executive. He is the executive chairman and co-founder of MicroStrategy, a company that provides business intelligence, mobile software, and cloud-based services. Saylor served as MicroStrategy's chief executive officer from 1989 to 2022. He authored the 2012 book The Mobile Wave: How Mobile Intelligence Will Change Everything. He is also the sole trustee of Saylor Academy, a provider of free online education. As of 2016, Saylor had been granted 31 patents and had 9 additional applications under review.\"})\n",
            "  ('Terra (blockchain)', {'url': 'https://en.wikipedia.org/wiki/Terra_(blockchain)', 'summary': 'Terra is a blockchain protocol and payment platform used for algorithmic stablecoins. The project was created in 2018 by Terraform Labs, a startup co-founded by Do Kwon and Daniel Shin. It is most known for its Terra stablecoin and the associated Luna reserve asset cryptocurrency.\\nIn May 2022, the Terra blockchain was temporarily halted after the collapse of the stablecoin TerraUSD (UST) and Luna, in the event that wiped out almost $45 billion in market capitalisation within a week.'})\n",
            "  ('Stablecoin', {'url': 'https://en.wikipedia.org/wiki/Stablecoin', 'summary': 'A stablecoin is a type of cryptocurrency where the value of the digital asset is supposed to be pegged to a reference asset, which is either fiat money, exchange-traded commodities (such as precious metals or industrial metals), or another cryptocurrency.In theory, 1:1 backing by a reference asset could make a stablecoin value track the value of the peg and not be subject to the radical changes in value common in the market for many digital assets. In practice, however, stablecoin issuers have yet to be proven to maintain adequate reserves to support a stable value and there have been a number of failures with investors losing the entirety of the (fiat currency) value of their holdings.'})\n",
            "  ('Security token', {'url': 'https://en.wikipedia.org/wiki/Security_token', 'summary': 'A security token is a peripheral device used to gain access to an electronically restricted resource. The token is used in addition to, or in place of, a password. It acts like an electronic key to access something. Examples of security tokens include wireless keycards used to open locked doors, or a banking token used as a digital authenticator for signing in to online banking, or signing a transaction such as a wire transfer.\\nSecurity tokens can be used to store information such as passwords, cryptographic keys used to generate digital signatures, or biometric data (such as fingerprints). Some designs incorporate tamper resistant packaging, while others may include small keypads to allow entry of a PIN or a simple button to start a generating routine with some display capability to show a generated key number. Connected tokens utilize a variety of interfaces including USB, near-field communication (NFC), radio-frequency identification (RFID), or Bluetooth. Some tokens have audio capabilities designed for those who are vision-impaired.'})\n",
            "  ('Bitcoin', {'url': 'https://en.wikipedia.org/wiki/Bitcoin', 'summary': 'Bitcoin (abbreviation: BTC or XBT; sign: ₿) is the first decentralized cryptocurrency. Nodes in the peer-to-peer bitcoin network verify transactions through cryptography and record them in a public distributed ledger, called a blockchain, without central oversight. Consensus between nodes is achieved using a computationally intensive system based on proof-of-work called mining. Bitcoin mining requires increasing quantities of electricity and was responsible for 0.2% of world greenhouse gas emissions as of 2022.Based on a free market ideology, bitcoin was invented in 2008 by Satoshi Nakamoto, an unknown person. Use of bitcoin as a currency began in 2009, with the release of its open-source implementation.:\\u200ach. 1\\u200a In 2021, El Salvador adopted it as legal tender. Bitcoin is currently used more as a store of value and less as a medium of exchange or unit of account. It is mostly seen as an investment and has been described by many scholars as an economic bubble. As bitcoin is pseudonymous, its use by criminals has attracted the attention of regulators, leading to its ban by several countries as of 2021.'})\n",
            "  ('Cryptocurrency', {'url': 'https://en.wikipedia.org/wiki/Cryptocurrency', 'summary': 'A cryptocurrency, crypto-currency, or crypto is a digital currency designed to work as a medium of exchange through a computer network that is not reliant on any central authority, such as a government or bank, to uphold or maintain it. It is a decentralized system for verifying that the parties to a transaction have the money they claim to have, eliminating the need for traditional intermediaries, such as banks, when funds are being transferred between two entities.Individual coin ownership records are stored in a digital ledger, which is a computerized database using strong cryptography to secure transaction records, control the creation of additional coins, and verify the transfer of coin ownership. Despite their name, cryptocurrencies are not considered to be currencies in the traditional sense, and while varying treatments have been applied to them, including classification as commodities, securities, and currencies, cryptocurrencies are generally viewed as a distinct asset class in practice. Some crypto schemes use validators to maintain the cryptocurrency. In a proof-of-stake model, owners put up their tokens as collateral. In return, they get authority over the token in proportion to the amount they stake. Generally, these token stakers get additional ownership in the token over time via network fees, newly minted tokens, or other such reward mechanisms.Cryptocurrency does not exist in physical form (like paper money) and is typically not issued by a central authority. Cryptocurrencies typically use decentralized control as opposed to a central bank digital currency (CBDC). When a cryptocurrency is minted, or created prior to issuance, or issued by a single issuer, it is generally considered centralized. When implemented with decentralized control, each cryptocurrency works through distributed ledger technology, typically a blockchain, that serves as a public financial transaction database.The first cryptocurrency was Bitcoin, which was first released as open-source software in 2009. As of June 2023, there were more than 25,000 other cryptocurrencies in the marketplace, of which more than 40 had a market capitalization exceeding $1 billion.'})\n",
            "  ('Lightning', {'url': 'https://en.wikipedia.org/wiki/Lightning', 'summary': 'Lightning is a natural phenomenon formed by electrostatic discharges through the atmosphere between two electrically charged regions, either both in the atmosphere or with one in the atmosphere and on the ground, temporarily neutralizing these in a near-instantaneous release of an average of one gigajoule of energy. This discharge may produce a wide range of electromagnetic radiation, from heat created by the rapid movement of electrons, to brilliant flashes of visible light in the form of black-body radiation. Lightning causes thunder, a sound from the shock wave which develops as gases in the vicinity of the discharge experience a sudden increase in pressure. Lightning occurs commonly during thunderstorms as well as other types of energetic weather systems, but volcanic lightning can also occur during volcanic eruptions. Lightning is an atmospheric electrical phenomenon and contributes to the global atmospheric electrical circuit.\\nThe three main kinds of lightning are distinguished by where they occur: either inside a single thundercloud (intra-cloud), between two clouds (cloud-to-cloud), or between a cloud and the ground (cloud-to-ground), in which case it is referred to as a lightning strike. Many other observational variants are recognized, including \"heat lightning\", which can be seen from a great distance but not heard; dry lightning, which can cause forest fires; and ball lightning, which is rarely observed scientifically.\\nHumans have deified lightning for millennia. Idiomatic expressions derived from lightning, such as the English expression \"bolt from the blue\", are common across languages. At all times people have been fascinated by the sight and difference of lightning. The fear of lightning is called astraphobia.\\nThe first known photograph of lightning is from 1847, by Thomas Martin Easterly. The first surviving photograph is from 1882, by William Nicholson Jennings, a photographer who spent half his life capturing pictures of lightning and proving its diversity.\\nThere is growing evidence that lightning activity is increased by particulate emissions (a form of air pollution). However, lightning may also improve air quality and clean greenhouse gases such as methane from the atmosphere, while creating nitrogen oxide and ozone at the same time. Lightning is also the major cause of wildfire, and wildfire can contribute to climate change as well. More studies are warranted to clarify their relationship.'})\n",
            "Relations:\n",
            "  {'head': 'MicroStrategy', 'type': 'founded by', 'tail': 'Michael J. Saylor', 'meta': {'https://finance.yahoo.com/news/microstrategy-bitcoin-millions-142143795.html': {'spans': [[0, 128]]}}}\n",
            "  {'head': 'Michael J. Saylor', 'type': 'employer', 'tail': 'MicroStrategy', 'meta': {'https://finance.yahoo.com/news/microstrategy-bitcoin-millions-142143795.html': {'spans': [[0, 128]]}}}\n",
            "  {'head': 'MicroStrategy', 'type': 'owned by', 'tail': 'Michael J. Saylor', 'meta': {'https://finance.yahoo.com/news/microstrategy-bitcoin-millions-142143795.html': {'spans': [[0, 128]]}}}\n",
            "  {'head': 'Terra (blockchain)', 'type': 'instance of', 'tail': 'Stablecoin', 'meta': {'https://finance.yahoo.com/news/microstrategy-bitcoin-millions-142143795.html': {'spans': [[114, 242]]}}}\n",
            "  {'head': 'Terra (blockchain)', 'type': 'instance of', 'tail': 'Security token', 'meta': {'https://finance.yahoo.com/news/microstrategy-bitcoin-millions-142143795.html': {'spans': [[114, 242]]}}}\n",
            "  {'head': 'Bitcoin', 'type': 'instance of', 'tail': 'Cryptocurrency', 'meta': {'https://finance.yahoo.com/news/microstrategy-bitcoin-millions-142143795.html': {'spans': [[228, 356], [456, 584]]}}}\n",
            "  {'head': 'Bitcoin', 'type': 'uses', 'tail': 'Lightning', 'meta': {'https://finance.yahoo.com/news/microstrategy-bitcoin-millions-142143795.html': {'spans': [[342, 470]]}}}\n",
            "  {'head': 'Lightning', 'type': 'used by', 'tail': 'Bitcoin', 'meta': {'https://finance.yahoo.com/news/microstrategy-bitcoin-millions-142143795.html': {'spans': [[342, 470]]}}}\n",
            "  {'head': 'Bitcoin', 'type': 'used by', 'tail': 'Lightning', 'meta': {'https://finance.yahoo.com/news/microstrategy-bitcoin-millions-142143795.html': {'spans': [[342, 470]]}}}\n",
            "  {'head': 'Lightning', 'type': 'instance of', 'tail': 'Cryptocurrency', 'meta': {'https://finance.yahoo.com/news/microstrategy-bitcoin-millions-142143795.html': {'spans': [[456, 584]]}}}\n",
            "Sources:\n",
            "  ('https://finance.yahoo.com/news/microstrategy-bitcoin-millions-142143795.html', {'article_title': \"Microstrategy chief: 'Bitcoin is going to go into the millions'\", 'article_publish_date': None})\n"
          ]
        }
      ],
      "source": [
        "url = \"https://finance.yahoo.com/news/microstrategy-bitcoin-millions-142143795.html\"\n",
        "kb = from_url_to_kb(url)\n",
        "kb.print()\n",
        "# Entities:\n",
        "#   ('MicroStrategy', {'url': 'https://en.wikipedia.org/wiki/MicroStrategy',\n",
        "#     'summary': \"MicroStrategy Incorporated is an American company that ...\"})\n",
        "#   ('Michael J. Saylor', {'url': 'https://en.wikipedia.org/wiki/Michael_J._Saylor',\n",
        "#     'summary': 'Michael J. Saylor (born February 4, 1965) is an American ...\"})\n",
        "#   ...\n",
        "# Relations:\n",
        "#   {'head': 'MicroStrategy', 'type': 'founded by', 'tail': 'Michael J. Saylor',\n",
        "#    'meta': {'https://finance.yahoo.com/news/microstrategy-bitcoin-millions-142143795.html':\n",
        "#      {'spans': [[0, 128]]}}}\n",
        "#   {'head': 'Michael J. Saylor', 'type': 'employer', 'tail': 'MicroStrategy',\n",
        "#    'meta': {'https://finance.yahoo.com/news/microstrategy-bitcoin-millions-142143795.html':\n",
        "#      {'spans': [[0, 128]]}}}\n",
        "#   ...\n",
        "# Sources:\n",
        "#   ('https://finance.yahoo.com/news/microstrategy-bitcoin-millions-142143795.html',\n",
        "#     {'article_title': \"Microstrategy chief: 'Bitcoin is going to go into the millions'\",\n",
        "#      'article_publish_date': None})"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "cyw2uyQ8xjUs"
      },
      "source": [
        "# Google 新闻：从多篇文章中提取 KB"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "LPx7aqWnxmUe"
      },
      "outputs": [],
      "source": [
        "def get_news_links(query, lang=\"en\", region=\"US\", pages=1, max_links=100000):\n",
        "    googlenews = GoogleNews(lang=lang, region=region)\n",
        "    googlenews.search(query)\n",
        "    all_urls = []\n",
        "    for page in range(pages):\n",
        "        googlenews.get_page(page)\n",
        "        all_urls += googlenews.get_links()\n",
        "    return list(set(all_urls))[:max_links]\n",
        "\n",
        "def from_urls_to_kb(urls, verbose=False):\n",
        "    kb = KB()\n",
        "    if verbose:\n",
        "        print(f\"{len(urls)} links to visit\")\n",
        "    for url in urls:\n",
        "        if verbose:\n",
        "            print(f\"Visiting {url}...\")\n",
        "        try:\n",
        "            kb_url = from_url_to_kb(url)\n",
        "            kb.merge_with_kb(kb_url)\n",
        "        except ArticleException:\n",
        "            if verbose:\n",
        "                print(f\"  Couldn't download article at url {url}\")\n",
        "    return kb"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "Rmi0jZouR2XY"
      },
      "outputs": [],
      "source": [
        "import pickle\n",
        "\n",
        "def save_kb(kb, filename):\n",
        "    with open(filename, \"wb\") as f:\n",
        "        pickle.dump(kb, f)\n",
        "\n",
        "def load_kb(filename):\n",
        "    res = None\n",
        "    with open(filename, \"rb\") as f:\n",
        "        res = pickle.load(f)\n",
        "    return res"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "VcyzPTW-yg-F",
        "outputId": "b8b54d8d-010e-4180-e5d0-ed335ea315f2"
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "3 links to visit\n",
            "Visiting https://9to5google.com/2023/12/11/google-search-2023-recap/&ved=2ahUKEwjD9ojSsImDAxV7k2oFHT5qCbwQxfQBegQIABAC&usg=AOvVaw3F7pNMGRrgzSyex9i9ixSD...\n",
            "  Couldn't download article at url https://9to5google.com/2023/12/11/google-search-2023-recap/&ved=2ahUKEwjD9ojSsImDAxV7k2oFHT5qCbwQxfQBegQIABAC&usg=AOvVaw3F7pNMGRrgzSyex9i9ixSD\n",
            "Visiting https://thecryptobasic.com/2023/12/12/google-bard-predicts-xrp-price-after-bitcoin-halving/&ved=2ahUKEwjD9ojSsImDAxV7k2oFHT5qCbwQxfQBegQIBRAC&usg=AOvVaw182icTdG8LHjQmosNx7N8I...\n",
            "  Couldn't download article at url https://thecryptobasic.com/2023/12/12/google-bard-predicts-xrp-price-after-bitcoin-halving/&ved=2ahUKEwjD9ojSsImDAxV7k2oFHT5qCbwQxfQBegQIBRAC&usg=AOvVaw182icTdG8LHjQmosNx7N8I\n",
            "Visiting https://9to5google.com/2023/12/11/pixel-watch-2-first-google-discount/&ved=2ahUKEwjD9ojSsImDAxV7k2oFHT5qCbwQxfQBegQIBBAC&usg=AOvVaw04bBilAjgH_ZjyqB6vDTCl...\n",
            "  Couldn't download article at url https://9to5google.com/2023/12/11/pixel-watch-2-first-google-discount/&ved=2ahUKEwjD9ojSsImDAxV7k2oFHT5qCbwQxfQBegQIBBAC&usg=AOvVaw04bBilAjgH_ZjyqB6vDTCl\n",
            "Entities:\n",
            "Relations:\n",
            "Sources:\n"
          ]
        }
      ],
      "source": [
        "news_links = get_news_links(\"Google\", pages=1, max_links=3)\n",
        "kb = from_urls_to_kb(news_links, verbose=True)\n",
        "kb.print()\n",
        "# 3 links to visit\n",
        "# Visiting https://www.hindustantimes.com/india-news/google-doodle-celebrates-india-s-gama-pehlwan-the-undefeated-wrestling-champion-101653180853982.html...\n",
        "# Visiting https://tech.hindustantimes.com/tech/news/google-doodle-today-celebrates-gama-pehlwan-s-144th-birth-anniversary-know-who-he-is-71653191916538.html...\n",
        "# Visiting https://www.moneycontrol.com/news/trends/current-affairs-trends/google-doodle-celebrates-gama-pehlwan-the-amritsar-born-wrestling-champ-who-inspired-bruce-lee-8552171.html...\n",
        "# Entities:\n",
        "#   ('Google', {'url': 'https://en.wikipedia.org/wiki/Google',\n",
        "#     'summary': 'Google LLC is an American ...'})\n",
        "#   ...\n",
        "# Relations:\n",
        "#   {'head': 'Google', 'type': 'owner of', 'tail': 'Google Doodle',\n",
        "#     'meta': {'https://tech.hindustantimes.com/tech/news/google-doodle-today-celebrates-gama-pehlwan-s-144th-birth-anniversary-know-who-he-is-71653191916538.html':\n",
        "#       {'spans': [[0, 128]]}}}\n",
        "#   ...\n",
        "# Sources:\n",
        "#   ('https://www.hindustantimes.com/india-news/google-doodle-celebrates-india-s-gama-pehlwan-the-undefeated-wrestling-champion-101653180853982.html',\n",
        "#     {'article_title': \"Google Doodle celebrates India's Gama Pehlwan, the undefeated wrestling champion\",\n",
        "#     'article_publish_date': datetime.datetime(2022, 5, 22, 6, 59, 56, tzinfo=tzoffset(None, 19800))})\n",
        "#   ('https://tech.hindustantimes.com/tech/news/google-doodle-today-celebrates-gama-pehlwan-s-144th-birth-anniversary-know-who-he-is-71653191916538.html',\n",
        "#     {'article_title': \"Google Doodle today celebrates Gama Pehlwan's 144th birth anniversary; know who he is\",\n",
        "#     'article_publish_date': datetime.datetime(2022, 5, 22, 9, 32, 38, tzinfo=tzoffset(None, 19800))})\n",
        "#   ('https://www.moneycontrol.com/news/trends/current-affairs-trends/google-doodle-celebrates-gama-pehlwan-the-amritsar-born-wrestling-champ-who-inspired-bruce-lee-8552171.html',\n",
        "#     {'article_title': 'Google Doodle celebrates Gama Pehlwan, the Amritsar-born wrestling champ who inspired Bruce Lee',\n",
        "#     'article_publish_date': None})"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "faxFpyvT1b4q"
      },
      "source": [
        "# 可视化 KB"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 40,
      "metadata": {
        "id": "m_aOZRSJ3rah"
      },
      "outputs": [],
      "source": [
        "def save_network_html(kb, filename=\"network.html\"):\n",
        "    # create network\n",
        "    net = Network(directed=True, width=\"700px\", height=\"700px\", bgcolor=\"#eeeeee\")\n",
        "\n",
        "    # nodes\n",
        "    color_entity = \"#00FF00\"\n",
        "    for e in kb.entities:\n",
        "        net.add_node(e, shape=\"circle\", color=color_entity)\n",
        "\n",
        "    # edges\n",
        "    for r in kb.relations:\n",
        "        net.add_edge(r[\"head\"], r[\"tail\"],\n",
        "                    title=r[\"type\"], label=r[\"type\"])\n",
        "\n",
        "    # save network\n",
        "    net.repulsion(\n",
        "        node_distance=200,\n",
        "        central_gravity=0.2,\n",
        "        spring_length=200,\n",
        "        spring_strength=0.05,\n",
        "        damping=0.09\n",
        "    )\n",
        "    net.set_edge_smooth('dynamic')\n",
        "    net.show(filename)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "tpLEMFwDepVI"
      },
      "outputs": [],
      "source": [
        "news_links = get_news_links(\"Google\", pages=5, max_links=20)\n",
        "kb = from_urls_to_kb(news_links, verbose=True)\n",
        "filename = \"network_3_google.html\"\n",
        "save_network_html(kb, filename=filename)\n",
        "IPython.display.HTML(filename=filename)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "f3-dUMvcEV5u"
      },
      "outputs": [],
      "source": [
        "news_links = get_news_links(\"Google\", pages=5, max_links=20)\n",
        "kb = from_urls_to_kb(news_links, verbose=True)\n",
        "filename = \"network_3_google.html\"\n",
        "save_network_html(kb, filename=filename)\n",
        "save_kb(kb, filename.split(\".\")[0] + \".p\")\n",
        "IPython.display.HTML(filename=filename)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "TwqmNpcvlUTK"
      },
      "outputs": [],
      "source": [
        "news_links = get_news_links(\"Amazon\", pages=5, max_links=20)\n",
        "kb = from_urls_to_kb(news_links, verbose=True)\n",
        "filename = \"network_3_amazon.html\"\n",
        "save_network_html(kb, filename=filename)\n",
        "save_kb(kb, filename.split(\".\")[0] + \".p\")\n",
        "IPython.display.HTML(filename=filename)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "28N51AuzlURR"
      },
      "outputs": [],
      "source": [
        "news_links = get_news_links(\"Apple\", pages=5, max_links=20)\n",
        "kb = from_urls_to_kb(news_links, verbose=True)\n",
        "filename = \"network_3_apple.html\"\n",
        "save_network_html(kb, filename=filename)\n",
        "save_kb(kb, filename.split(\".\")[0] + \".p\")\n",
        "IPython.display.HTML(filename=filename)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "xPPgT-FWlUPK"
      },
      "outputs": [],
      "source": [
        "news_links = get_news_links(\"Elon Musk\", pages=5, max_links=20)\n",
        "kb = from_urls_to_kb(news_links, verbose=True)\n",
        "filename = \"network_3_musk.html\"\n",
        "save_network_html(kb, filename=filename)\n",
        "save_kb(kb, filename.split(\".\")[0] + \".p\")\n",
        "IPython.display.HTML(filename=filename)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "5qoOAMIslUMe"
      },
      "outputs": [],
      "source": [
        "news_links = get_news_links(\"Kobe Bryant\", pages=5, max_links=20)\n",
        "kb = from_urls_to_kb(news_links, verbose=True)\n",
        "filename = \"network_3_bryant.html\"\n",
        "save_network_html(kb, filename=filename)\n",
        "save_kb(kb, filename.split(\".\")[0] + \".p\")\n",
        "IPython.display.HTML(filename=filename)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 44,
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 520
        },
        "id": "33OgmsCwNVlg",
        "outputId": "9fbb939a-61ac-42ec-be3a-90fb90d731af"
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Input has 133 tokens\n",
            "Input has 2 spans\n",
            "Span boundaries are [[0, 128], [5, 133]]\n"
          ]
        },
        {
          "ename": "TypeError",
          "evalue": "ignored",
          "output_type": "error",
          "traceback": [
            "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
            "\u001b[0;31mTypeError\u001b[0m                                 Traceback (most recent call last)",
            "\u001b[0;32m<ipython-input-44-8960cc2e534f>\u001b[0m in \u001b[0;36m<cell line: 2>\u001b[0;34m()\u001b[0m\n\u001b[1;32m      1\u001b[0m \u001b[0mtext\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m\"Napoleon Bonaparte (born Napoleone di Buonaparte; 15 August 1769 – 5 May 1821), and later known by his regnal name Napoleon I, was a French military and political leader who rose to prominence during the French Revolution and led several successful campaigns during the Revolutionary Wars. He was the de facto leader of the French Republic as First Consul from 1799 to 1804. As Napoleon I, he was Emperor of the French from 1804 until 1814 and again in 1815. Napoleon's political and cultural legacy has endured, and he has been one of the most celebrated and controversial leaders in world history.\"\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 2\u001b[0;31m \u001b[0mkb\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mfrom_text_to_kb\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mtext\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m\"\"\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mverbose\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;32mTrue\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m      3\u001b[0m \u001b[0mfilename\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m\"network_1_napoleon.html\"\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m      4\u001b[0m \u001b[0msave_network_html\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mkb\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mfilename\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mfilename\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m      5\u001b[0m \u001b[0msave_kb\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mkb\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mfilename\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0msplit\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\".\"\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m0\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;34m+\u001b[0m \u001b[0;34m\".p\"\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
            "\u001b[0;32m<ipython-input-43-af1d94347428>\u001b[0m in \u001b[0;36mfrom_text_to_kb\u001b[0;34m(text, article_url, span_length, article_title, article_publish_date, verbose)\u001b[0m\n\u001b[1;32m     61\u001b[0m                 }\n\u001b[1;32m     62\u001b[0m             }\n\u001b[0;32m---> 63\u001b[0;31m             \u001b[0mkb\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0madd_relation\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mrelation\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0marticle_title\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m     64\u001b[0m         \u001b[0mi\u001b[0m \u001b[0;34m+=\u001b[0m \u001b[0;36m1\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m     65\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n",
            "\u001b[0;31mTypeError\u001b[0m: KB.add_relation() takes 2 positional arguments but 3 were given"
          ]
        }
      ],
      "source": [
        "text = \"Napoleon Bonaparte (born Napoleone di Buonaparte; 15 August 1769 – 5 May 1821), and later known by his regnal name Napoleon I, was a French military and political leader who rose to prominence during the French Revolution and led several successful campaigns during the Revolutionary Wars. He was the de facto leader of the French Republic as First Consul from 1799 to 1804. As Napoleon I, he was Emperor of the French from 1804 until 1814 and again in 1815. Napoleon's political and cultural legacy has endured, and he has been one of the most celebrated and controversial leaders in world history.\"\n",
        "kb = from_text_to_kb(text, \"\", verbose=True)\n",
        "filename = \"network_1_napoleon.html\"\n",
        "save_network_html(kb, filename=filename)\n",
        "save_kb(kb, filename.split(\".\")[0] + \".p\")\n",
        "IPython.display.HTML(filename=filename)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "XVhlJJMNNVjE"
      },
      "outputs": [],
      "source": [
        "text = \"Kobe Bean Bryant (August 23, 1978 – January 26, 2020) was an American professional basketball player. A shooting guard, he spent his entire 20-year career with the Los Angeles Lakers in the National Basketball Association (NBA). Widely regarded as one of the greatest basketball players of all time, Bryant won five NBA championships, was an 18-time All-Star, a 15-time member of the All-NBA Team, a 12-time member of the All-Defensive Team, the 2008 NBA Most Valuable Player (MVP), and a two-time NBA Finals MVP. Bryant also led the NBA in scoring twice, and ranks fourth in league all-time regular season and postseason scoring. He was posthumously voted into the Naismith Memorial Basketball Hall of Fame in 2020 and named to the NBA 75th Anniversary Team in 2021.\"\n",
        "kb = from_text_to_kb(text, \"\", verbose=True)\n",
        "filename = \"network_1_bryant.html\"\n",
        "save_network_html(kb, filename=filename)\n",
        "save_kb(kb, filename.split(\".\")[0] + \".p\")\n",
        "IPython.display.HTML(filename=filename)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "6d4u9pfLNVgZ"
      },
      "outputs": [],
      "source": [
        "text = \"Originally known as BackRub. Google is a search engine that started development in 1996 by Sergey Brin and Larry Page as a research project at Stanford University to find files on the Internet. Larry and Sergey later decided the name of their search engine needed to change and chose Google, which is inspired from the term googol. The company is headquartered in Mountain View, California.\"\n",
        "kb = from_text_to_kb(text, \"\", verbose=True)\n",
        "filename = \"network_1_google.html\"\n",
        "save_network_html(kb, filename=filename)\n",
        "save_kb(kb, filename.split(\".\")[0] + \".p\")\n",
        "IPython.display.HTML(filename=filename)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "aawuSQTpNVcb"
      },
      "outputs": [],
      "source": [
        "url = \"https://www.investopedia.com/terms/c/cryptocurrency.asp\"\n",
        "kb = from_url_to_kb(url)\n",
        "filename = \"network_2_crypto.html\"\n",
        "save_network_html(kb, filename=filename)\n",
        "save_kb(kb, filename.split(\".\")[0] + \".p\")\n",
        "IPython.display.HTML(filename=filename)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "VWTnquxcOCys"
      },
      "outputs": [],
      "source": [
        "url = \"https://www.britannica.com/biography/Johnny-Depp\"\n",
        "kb = from_url_to_kb(url)\n",
        "filename = \"network_2_depp.html\"\n",
        "save_network_html(kb, filename=filename)\n",
        "save_kb(kb, filename.split(\".\")[0] + \".p\")\n",
        "IPython.display.HTML(filename=filename)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 47,
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 419
        },
        "id": "_bdca4ugOEF5",
        "outputId": "f39cdd9b-e4db-4b97-b654-d350fc407b08"
      },
      "outputs": [
        {
          "ename": "TypeError",
          "evalue": "ignored",
          "output_type": "error",
          "traceback": [
            "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
            "\u001b[0;31mTypeError\u001b[0m                                 Traceback (most recent call last)",
            "\u001b[0;32m<ipython-input-47-a253ce7556a1>\u001b[0m in \u001b[0;36m<cell line: 2>\u001b[0;34m()\u001b[0m\n\u001b[1;32m      1\u001b[0m \u001b[0murl\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m\"https://www.timeout.com/rome/things-to-do/best-things-to-do-in-rome\"\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 2\u001b[0;31m \u001b[0mkb\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mfrom_url_to_kb\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0murl\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m      3\u001b[0m \u001b[0mfilename\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m\"network_2_rome.html\"\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m      4\u001b[0m \u001b[0msave_network_html\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mkb\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mfilename\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mfilename\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m      5\u001b[0m \u001b[0msave_kb\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mkb\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mfilename\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0msplit\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\".\"\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m0\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;34m+\u001b[0m \u001b[0;34m\".p\"\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
            "\u001b[0;32m<ipython-input-15-403323117d5d>\u001b[0m in \u001b[0;36mfrom_url_to_kb\u001b[0;34m(url)\u001b[0m\n\u001b[1;32m     11\u001b[0m         \u001b[0;34m\"article_publish_date\"\u001b[0m\u001b[0;34m:\u001b[0m \u001b[0marticle\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mpublish_date\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m     12\u001b[0m     }\n\u001b[0;32m---> 13\u001b[0;31m     \u001b[0mkb\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mfrom_text_to_kb\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0marticle\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mtext\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0marticle\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0murl\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mconfig\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m     14\u001b[0m     \u001b[0;32mreturn\u001b[0m \u001b[0mkb\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
            "\u001b[0;32m<ipython-input-46-0d421130be6f>\u001b[0m in \u001b[0;36mfrom_text_to_kb\u001b[0;34m(text, article_url, span_length, article_title, article_publish_date, verbose)\u001b[0m\n\u001b[1;32m     61\u001b[0m                 }\n\u001b[1;32m     62\u001b[0m             }\n\u001b[0;32m---> 63\u001b[0;31m             \u001b[0mkb\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0madd_relation\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mrelation\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0marticle_title\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0marticle_publish_date\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m     64\u001b[0m         \u001b[0mi\u001b[0m \u001b[0;34m+=\u001b[0m \u001b[0;36m1\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m     65\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n",
            "\u001b[0;31mTypeError\u001b[0m: KB.add_relation() takes 2 positional arguments but 4 were given"
          ]
        }
      ],
      "source": [
        "url = \"https://www.timeout.com/rome/things-to-do/best-things-to-do-in-rome\"\n",
        "kb = from_url_to_kb(url)\n",
        "filename = \"network_2_rome.html\"\n",
        "save_network_html(kb, filename=filename)\n",
        "save_kb(kb, filename.split(\".\")[0] + \".p\")\n",
        "IPython.display.HTML(filename=filename)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "KSR7MqqVOXh2"
      },
      "outputs": [],
      "source": []
    }
  ],
  "metadata": {
    "colab": {
      "collapsed_sections": [
        "MqhLveaeuJNk",
        "c13w1wTF61AB",
        "cyw2uyQ8xjUs"
      ],
      "provenance": []
    },
    "kernelspec": {
      "display_name": "Python 3",
      "name": "python3"
    },
    "language_info": {
      "codemirror_mode": {
        "name": "ipython",
        "version": 3
      },
      "file_extension": ".py",
      "mimetype": "text/x-python",
      "name": "python",
      "nbconvert_exporter": "python",
      "pygments_lexer": "ipython3",
      "version": "3.12.0"
    }
  },
  "nbformat": 4,
  "nbformat_minor": 0
}
